From 7156e086f6ba6993db87396e133b8158bed882c8 Mon Sep 17 00:00:00 2001 From: kumquat-ir <66188216+kumquat-ir@users.noreply.github.com> Date: Fri, 16 Apr 2021 13:33:56 -0700 Subject: [PATCH] parse META-INF/mods.toml for metadata --- api/logic/CMakeLists.txt | 2 +- api/logic/minecraft/mod/LocalModParseTask.cpp | 74 ++++++++++++++++++- 2 files changed, 74 insertions(+), 2 deletions(-) diff --git a/api/logic/CMakeLists.txt b/api/logic/CMakeLists.txt index beaa0c00..23bf848d 100644 --- a/api/logic/CMakeLists.txt +++ b/api/logic/CMakeLists.txt @@ -540,7 +540,7 @@ set_target_properties(MultiMC_logic PROPERTIES CXX_VISIBILITY_PRESET hidden VISI generate_export_header(MultiMC_logic) # Link -target_link_libraries(MultiMC_logic systeminfo MultiMC_quazip MultiMC_classparser ${NBT_NAME} ${ZLIB_LIBRARIES} optional-bare BuildConfig) +target_link_libraries(MultiMC_logic systeminfo MultiMC_quazip MultiMC_classparser ${NBT_NAME} ${ZLIB_LIBRARIES} optional-bare toml11 BuildConfig) target_link_libraries(MultiMC_logic Qt5::Core Qt5::Xml Qt5::Network Qt5::Concurrent) # Mark and export headers diff --git a/api/logic/minecraft/mod/LocalModParseTask.cpp b/api/logic/minecraft/mod/LocalModParseTask.cpp index 22ebd7d4..cb35dca6 100644 --- a/api/logic/minecraft/mod/LocalModParseTask.cpp +++ b/api/logic/minecraft/mod/LocalModParseTask.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "settings/INIFile.h" #include "FileSystem.h" @@ -90,6 +91,64 @@ std::shared_ptr ReadMCModInfo(QByteArray contents) return nullptr; } + +std::shared_ptr ReadMCModTOML(QByteArray contents) +{ + std::shared_ptr details = std::make_shared(); + + // toml11 throws an error when something goes wrong in parsing, so we need to catch that + try { + // data under the root table + auto tomlData = toml::parse(contents); + // data under [[mods]] + auto tomlModsArr = toml::find>(tomlData, "mods"); + + // these properties are required in this location by forge, and thus can be assumed to exist + // forge supports multiple mods in one file, details of which are accessable here from tomlModsArr[n] + details->mod_id = QString::fromStdString(toml::find(tomlModsArr[0], "modId")); + details->version = QString::fromStdString(toml::find(tomlModsArr[0], "version")); + details->name = QString::fromStdString(toml::find(tomlModsArr[0], "displayName")); + // known issue: sometimes overflows the description box for some reason + details->description = QString::fromStdString(toml::find(tomlModsArr[0], "description")); + + // optional properties - can be stored either in the root table or in [[mods]] + auto authors = QString::fromStdString(toml::find_or(tomlData, "authors", "")); + if(authors.isEmpty()) + { + authors = QString::fromStdString(toml::find_or(tomlModsArr[0], "authors", "")); + } + if(!authors.isEmpty()) + { + // author information is stored as a string now, not a list + details->authors.append(authors); + } + // is credits even used anywhere? including this for completion/parity with old data version + auto credits = QString::fromStdString(toml::find_or(tomlData, "credits", "")); + if(credits.isEmpty()) + { + credits = QString::fromStdString(toml::find_or(tomlModsArr[0], "credits", "")); + } + details->credits = credits; + auto homeurl = QString::fromStdString(toml::find_or(tomlData, "displayURL", "")); + if(homeurl.isEmpty()) + { + homeurl = QString::fromStdString(toml::find_or(tomlModsArr[0], "displayURL", "")); + } + if(!homeurl.isEmpty()) + { + // fix up url. + if (!homeurl.startsWith("http://") && !homeurl.startsWith("https://") && !homeurl.startsWith("ftp://")) + { + homeurl.prepend("http://"); + } + } + details->homeurl = homeurl; + } catch (toml::syntax_error&) { + return nullptr; + } + return details; +} + // https://fabricmc.net/wiki/documentation:fabric_mod_json std::shared_ptr ReadFabricModInfo(QByteArray contents) { @@ -198,7 +257,20 @@ void LocalModParseTask::processAsZip() QuaZipFile file(&zip); - if (zip.setCurrentFile("mcmod.info")) + if (zip.setCurrentFile("META-INF/mods.toml")) + { + if (!file.open(QIODevice::ReadOnly)) + { + zip.close(); + return; + } + + m_result->details = ReadMCModTOML(file.readAll()); + file.close(); + zip.close(); + return; + } + else if (zip.setCurrentFile("mcmod.info")) { if (!file.open(QIODevice::ReadOnly)) {