diff --git a/loader/include/Geode/loader/ModMetadata.hpp b/loader/include/Geode/loader/ModMetadata.hpp index d0e3c793..b3b8454c 100644 --- a/loader/include/Geode/loader/ModMetadata.hpp +++ b/loader/include/Geode/loader/ModMetadata.hpp @@ -236,6 +236,8 @@ namespace geode { void setTags(std::unordered_set const& value); void setNeedsEarlyLoad(bool const& value); void setIsAPI(bool const& value); + void setGameVersion(std::string const& value); + void setGeodeVersion(VersionInfo const& value); ModMetadataLinks& getLinksMut(); #endif diff --git a/loader/src/loader/ModMetadataImpl.cpp b/loader/src/loader/ModMetadataImpl.cpp index cacc4aa6..d3ebf8e5 100644 --- a/loader/src/loader/ModMetadataImpl.cpp +++ b/loader/src/loader/ModMetadataImpl.cpp @@ -654,6 +654,12 @@ void ModMetadata::setNeedsEarlyLoad(bool const& value) { void ModMetadata::setIsAPI(bool const& value) { m_impl->m_isAPI = value; } +void ModMetadata::setGameVersion(std::string const& value) { + m_impl->m_gdVersion = value; +} +void ModMetadata::setGeodeVersion(VersionInfo const& value) { + m_impl->m_geodeVersion = value; +} ModMetadataLinks& ModMetadata::getLinksMut() { return m_impl->m_links; } diff --git a/loader/src/server/Server.cpp b/loader/src/server/Server.cpp index 5fd6990e..cfdb195d 100644 --- a/loader/src/server/Server.cpp +++ b/loader/src/server/Server.cpp @@ -264,22 +264,17 @@ Result ServerModVersion::parse(matjson::Value const& raw) { auto res = ServerModVersion(); - // Verify target Geode version - auto version = root.needs("geode").template get(); - if (!semverCompare(Loader::get()->getVersion(), version)) { - return Err( - "Mod targets version {} but Geode is version {}", - version, Loader::get()->getVersion() - ); - } + res.metadata.setGeodeVersion(root.needs("geode").template get()); // Verify target GD version - auto gd = root.needs("gd").obj().needs(GEODE_PLATFORM_SHORT_IDENTIFIER).template get(); - if (gd != GEODE_GD_VERSION_STR && gd != "*") { - return Err( - "Mod targets GD version {} but current is version {}", - gd, GEODE_GD_VERSION_STR - ); + auto gd_obj = root.needs("gd").obj(); + std::string gd = "0.000"; + if (gd_obj.has(GEODE_PLATFORM_SHORT_IDENTIFIER)) { + gd = gd_obj.has(GEODE_PLATFORM_SHORT_IDENTIFIER).template get(); + } + + if (gd != "*") { + res.metadata.setGameVersion(gd); } // Get server info @@ -571,14 +566,15 @@ ServerRequest server::getMods(ModsQuery const& query, bool useCa auto req = web::WebRequest(); req.userAgent(getServerUserAgent()); - // Always target current GD version and Loader version - req.param("gd", GEODE_GD_VERSION_STR); - req.param("geode", Loader::get()->getVersion().toNonVString()); - // Add search params if (query.query) { req.param("query", *query.query); + } else { + // Target current GD version and Loader version when query is not set + req.param("gd", GEODE_GD_VERSION_STR); + req.param("geode", Loader::get()->getVersion().toNonVString()); } + if (query.platforms.size()) { std::string plats = ""; bool first = true; diff --git a/loader/src/ui/mods/list/ModItem.cpp b/loader/src/ui/mods/list/ModItem.cpp index ee85ab85..063b1a75 100644 --- a/loader/src/ui/mods/list/ModItem.cpp +++ b/loader/src/ui/mods/list/ModItem.cpp @@ -134,12 +134,27 @@ bool ModItem::init(ModSource&& source) { m_viewMenu->setAnchorPoint({ 1.f, .5f }); m_viewMenu->setScale(.55f); - ButtonSprite* spr; - if (Loader::get()->isModInstalled(m_source.getID())) { - spr = createGeodeButton("View", 50, false, true); - } else { - spr = createGeodeButton("Get", 50, false, true, GeodeButtonSprite::Install); + ButtonSprite* spr = nullptr; + if (auto serverMod = m_source.asServer(); serverMod != nullptr) { + auto version = serverMod->latestVersion(); + + auto geodeValid = Loader::get()->isModVersionSupported(version.getGeodeVersion()); + auto gameVersion = version.getGameVersion(); + auto gdValid = gameVersion == "*" || gameVersion == GEODE_STR(GEODE_GD_VERSION); + + if (!geodeValid || !gdValid) { + spr = createGeodeButton("NA", 50, false, true, GeodeButtonSprite::Default); + } } + + if (!spr) { + if (Loader::get()->isModInstalled(m_source.getID())) { + spr = createGeodeButton("View", 50, false, true); + } else { + spr = createGeodeButton("Get", 50, false, true, GeodeButtonSprite::Install); + } + } + auto viewBtn = CCMenuItemSpriteExtra::create( spr, this, menu_selector(ModItem::onView) @@ -473,6 +488,25 @@ void ModItem::onView(CCObject*) { )->show(); } + if (auto serverMod = m_source.asServer(); serverMod != nullptr) { + auto version = serverMod->latestVersion(); + auto geodeVersion = version.getGeodeVersion(); + auto geodeValid = Loader::get()->isModVersionSupported(geodeVersion); + + if (auto res = version.checkGameVersion(); !res) { + FLAlertLayer::create(nullptr, "Unavailable", res.unwrapErr(), "Close", nullptr)->show(); + return; + } else if (!geodeValid) { + auto msg = fmt::format( + "Geode {} is required to view this mod. You currently have {}.", + geodeVersion.toVString(), + Loader::get()->getVersion().toVString() + ); + FLAlertLayer::create(nullptr, "Unavailable", msg, "Close", nullptr)->show(); + return; + } + } + // Always open up the popup for the installed mod page if that is possible ModPopup::create(m_source.convertForPopup())->show(); } diff --git a/loader/src/ui/mods/sources/ServerModListSource.cpp b/loader/src/ui/mods/sources/ServerModListSource.cpp index d85e9f13..9ae8d828 100644 --- a/loader/src/ui/mods/sources/ServerModListSource.cpp +++ b/loader/src/ui/mods/sources/ServerModListSource.cpp @@ -80,7 +80,13 @@ ServerModListSource* ServerModListSource::get(ServerModListType type) { } void ServerModListSource::setSearchQuery(std::string const& query) { - m_query.query = query.size() ? std::optional(query) : std::nullopt; + if (query.empty()) { + m_query.query = std::nullopt; + m_query.platforms = { GEODE_PLATFORM_TARGET }; + } else { + m_query.query = std::optional(query); + m_query.platforms = {}; + } } std::unordered_set ServerModListSource::getModTags() const {