diff --git a/.github/ISSUE_TEMPLATE/feature-request.yml b/.github/ISSUE_TEMPLATE/feature-request.yml index e4a17ded..3ec80681 100644 --- a/.github/ISSUE_TEMPLATE/feature-request.yml +++ b/.github/ISSUE_TEMPLATE/feature-request.yml @@ -31,7 +31,7 @@ body: attributes: label: Additional Information description: Any additional information you wish to provide. Please add anything which did not fit into the other sections here. - placeholder: "Example: This is likely achieveable by doing X because..." + placeholder: "Example: This is likely achievable by doing X because..." validations: required: false - type: markdown diff --git a/CHANGELOG.md b/CHANGELOG.md index 428397b8..46955e8f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ * Add utils for setting thread name, show it on log (832bcf81, ce53fb31) * Add some launch arguments for geode (7ccaef90) * Deprecate blocking file picking utils (ee97e2da) + * Sort mods by id in crashlog (984d1482) ## v2.0.0-beta.11 diff --git a/loader/include/Geode/loader/Loader.hpp b/loader/include/Geode/loader/Loader.hpp index f36ef6f5..2ec88781 100644 --- a/loader/include/Geode/loader/Loader.hpp +++ b/loader/include/Geode/loader/Loader.hpp @@ -35,7 +35,9 @@ namespace geode { EnableFailed, MissingDependency, PresentIncompatibility, - UnzipFailed + UnzipFailed, + UnsupportedVersion, + UnsupportedGeodeVersion, }; Type type; std::variant cause; diff --git a/loader/include/Geode/loader/ModMetadata.hpp b/loader/include/Geode/loader/ModMetadata.hpp index de9f3e19..493af50f 100644 --- a/loader/include/Geode/loader/ModMetadata.hpp +++ b/loader/include/Geode/loader/ModMetadata.hpp @@ -161,6 +161,11 @@ namespace geode { */ [[nodiscard]] std::optional getGameVersion() const; + /** + * Gets the target Geode version for the current platform. + */ + [[nodiscard]] VersionInfo getGeodeVersion() const; + /** * Checks if mod can be installed on the current GD version. * Returns Ok() if it can, Err otherwise. diff --git a/loader/include/Geode/ui/Popup.hpp b/loader/include/Geode/ui/Popup.hpp index f59f0835..7aee8e65 100644 --- a/loader/include/Geode/ui/Popup.hpp +++ b/loader/include/Geode/ui/Popup.hpp @@ -19,6 +19,10 @@ namespace geode { cocos2d::CCTouchDispatcher::get()->unregisterForcePrio(this); } + void registerWithTouchDispatcher() override { + cocos2d::CCTouchDispatcher::get()->addTargetedDelegate(this, -500, true); + } + private: bool initBase( float width, float height, InitArgs... args, char const* bg, @@ -26,9 +30,11 @@ namespace geode { ) { m_dynamic = dynamic; - auto winSize = cocos2d::CCDirector::sharedDirector()->getWinSize(); + auto winSize = cocos2d::CCDirector::get()->getWinSize(); m_size = cocos2d::CCSize { width, height }; + cocos2d::CCTouchDispatcher::get()->registerForcePrio(this, 2); + if (!this->initWithColor({ 0, 0, 0, 105 })) return false; m_mainLayer = cocos2d::CCLayer::create(); this->addChild(m_mainLayer); @@ -76,10 +82,6 @@ namespace geode { this->setKeypadEnabled(true); this->setTouchEnabled(true); - cocos2d::CCTouchDispatcher::get()->registerForcePrio(this, 2); - - cocos::handleTouchPriority(this); - return true; } diff --git a/loader/include/Geode/utils/VersionInfo.hpp b/loader/include/Geode/utils/VersionInfo.hpp index 392a3c4b..3aca9db6 100644 --- a/loader/include/Geode/utils/VersionInfo.hpp +++ b/loader/include/Geode/utils/VersionInfo.hpp @@ -228,6 +228,8 @@ namespace geode { std::string toString() const; friend GEODE_DLL std::string format_as(ComparableVersionInfo const& version); }; + + bool GEODE_DLL semverCompare(VersionInfo const& current, VersionInfo const& target); } template diff --git a/loader/src/internal/crashlog.cpp b/loader/src/internal/crashlog.cpp index 2ab668a4..ae9913c3 100644 --- a/loader/src/internal/crashlog.cpp +++ b/loader/src/internal/crashlog.cpp @@ -31,6 +31,13 @@ void crashlog::printMods(std::stringstream& stream) { if (mods.empty()) { stream << "\n"; } + std::sort(mods.begin(), mods.end(), [](Mod* a, Mod* b) { + auto const s1 = a->getID(); + auto const s2 = b->getID(); + return std::lexicographical_compare(s1.begin(), s1.end(), s2.begin(), s2.end(), [](auto a, auto b) { + return std::tolower(a) < std::tolower(b); + }); + }); using namespace std::string_view_literals; for (auto& mod : mods) { stream << fmt::format("{} | [{}] {}\n", @@ -51,7 +58,7 @@ std::string crashlog::writeCrashlog(geode::Mod* faultyMod, std::string const& in std::stringstream file; file << getDateString(false) << "\n" - << std::showbase << "Whoopsies! An unhandled exception has occured.\n"; + << std::showbase << "Whoopsies! An unhandled exception has occurred.\n"; if (faultyMod) { file << "It appears that the crash occurred while executing code from " diff --git a/loader/src/loader/LoaderImpl.cpp b/loader/src/loader/LoaderImpl.cpp index 16efefb5..868c6458 100644 --- a/loader/src/loader/LoaderImpl.cpp +++ b/loader/src/loader/LoaderImpl.cpp @@ -148,10 +148,8 @@ VersionInfo Loader::Impl::maxModVersion() { }; } -bool Loader::Impl::isModVersionSupported(VersionInfo const& version) { - return - version >= this->minModVersion() && - version <= this->maxModVersion(); +bool Loader::Impl::isModVersionSupported(VersionInfo const& target) { + return semverCompare(this->getVersion(), target); } // Data saving @@ -421,6 +419,37 @@ void Loader::Impl::loadModGraph(Mod* node, bool early) { m_refreshingModCount -= 1; }; + { // version checking + auto res = node->getMetadata().checkGameVersion(); + if (!res) { + m_problems.push_back({ + LoadProblem::Type::UnsupportedVersion, + node, + res.unwrapErr() + }); + log::error("Unsupported game version: {}", res.unwrapErr()); + m_refreshingModCount -= 1; + log::popNest(); + return; + } + + if (!this->isModVersionSupported(node->getMetadata().getGeodeVersion())) { + m_problems.push_back({ + LoadProblem::Type::UnsupportedGeodeVersion, + node, + fmt::format( + "Geode version {} is not supported (current: {})", + node->getMetadata().getGeodeVersion().toString(), + this->getVersion().toString() + ) + }); + log::error("Unsupported Geode version: {}", node->getMetadata().getGeodeVersion()); + m_refreshingModCount -= 1; + log::popNest(); + return; + } + } + if (early) { auto res = unzipFunction(); if (!res) { diff --git a/loader/src/loader/ModImpl.cpp b/loader/src/loader/ModImpl.cpp index 43e89ef4..9b7255a8 100644 --- a/loader/src/loader/ModImpl.cpp +++ b/loader/src/loader/ModImpl.cpp @@ -357,8 +357,6 @@ bool Mod::Impl::getLaunchFlag(std::string_view const name) const { // Loading, Toggling, Installing Result<> Mod::Impl::loadBinary() { - // i dont know where to put this so ill just plop it here - GEODE_UNWRAP(m_metadata.checkGameVersion()); log::debug("Loading binary for mod {}", m_metadata.getID()); if (m_enabled) diff --git a/loader/src/loader/ModMetadataImpl.cpp b/loader/src/loader/ModMetadataImpl.cpp index 77bca83e..1ab858b6 100644 --- a/loader/src/loader/ModMetadataImpl.cpp +++ b/loader/src/loader/ModMetadataImpl.cpp @@ -67,7 +67,7 @@ Result ModMetadata::Impl::createFromSchemaV010(ModJson const& rawJs JsonChecker checker(impl->m_rawJSON); auto root = checker.root(checkerRoot).obj(); - root.addKnownKey("geode"); + root.needs("geode").into(impl->m_geodeVersion); root.addKnownKey("gd"); // Check GD version @@ -194,23 +194,23 @@ Result ModMetadata::Impl::create(ModJson const& json) { "specified, or its formatting is invalid (required: \"[v]X.X.X\")!" ); } - if (schema < Loader::get()->minModVersion()) { - return Err( - "[mod.json] is built for an older version (" + schema.toString() + - ") of Geode (current: " + Loader::get()->getVersion().toString() + - "). Please update the mod to the latest version, " - "and if the problem persists, contact the developer " - "to update it." - ); - } - if (schema > Loader::get()->maxModVersion()) { - return Err( - "[mod.json] is built for a newer version (" + schema.toString() + - ") of Geode (current: " + Loader::get()->getVersion().toString() + - "). You need to update Geode in order to use " - "this mod." - ); - } + // if (schema < Loader::get()->minModVersion()) { + // return Err( + // "[mod.json] is built for an older version (" + schema.toString() + + // ") of Geode (current: " + Loader::get()->getVersion().toString() + + // "). Please update the mod to the latest version, " + // "and if the problem persists, contact the developer " + // "to update it." + // ); + // } + // if (schema > Loader::get()->maxModVersion()) { + // return Err( + // "[mod.json] is built for a newer version (" + schema.toString() + + // ") of Geode (current: " + Loader::get()->getVersion().toString() + + // "). You need to update Geode in order to use " + // "this mod." + // ); + // } // Handle mod.json data based on target if (schema < VersionInfo(0, 1, 0)) { @@ -407,6 +407,10 @@ std::optional ModMetadata::getGameVersion() const { return m_impl->m_gdVersion; } +VersionInfo ModMetadata::getGeodeVersion() const { + return m_impl->m_geodeVersion; +} + Result<> ModMetadata::checkGameVersion() const { if (!m_impl->m_gdVersion.empty()) { auto const ver = m_impl->m_gdVersion; diff --git a/loader/src/loader/ModMetadataImpl.hpp b/loader/src/loader/ModMetadataImpl.hpp index e716587e..77c65f4f 100644 --- a/loader/src/loader/ModMetadataImpl.hpp +++ b/loader/src/loader/ModMetadataImpl.hpp @@ -17,6 +17,7 @@ namespace geode { std::string m_name; std::string m_developer; std::string m_gdVersion; + VersionInfo m_geodeVersion; std::optional m_description; std::optional m_details; std::optional m_changelog; diff --git a/loader/src/ui/internal/list/ModListLayer.cpp b/loader/src/ui/internal/list/ModListLayer.cpp index 14cf6d96..94d9d327 100644 --- a/loader/src/ui/internal/list/ModListLayer.cpp +++ b/loader/src/ui/internal/list/ModListLayer.cpp @@ -572,8 +572,6 @@ void ModListLayer::reloadList(bool keepScroll, std::optional const m_checkForUpdatesBtn->removeFromParent(); m_checkForUpdatesBtn = nullptr; } - - handleTouchPriority(this); } void ModListLayer::updateAllStates() { diff --git a/loader/src/ui/internal/list/ProblemsListCell.cpp b/loader/src/ui/internal/list/ProblemsListCell.cpp index 859df03a..f409b8c8 100644 --- a/loader/src/ui/internal/list/ProblemsListCell.cpp +++ b/loader/src/ui/internal/list/ProblemsListCell.cpp @@ -95,6 +95,16 @@ bool ProblemsListCell::init(LoadProblem problem, ProblemsListPopup* list, CCSize message = fmt::format("{} has failed unzipping", cause); m_longMessage = problem.message; break; + case LoadProblem::Type::UnsupportedVersion: + icon = "info-alert.png"_spr; + message = fmt::format("{} is incompatible with this version of GD", cause); + m_longMessage = problem.message; + break; + case LoadProblem::Type::UnsupportedGeodeVersion: + icon = "info-alert.png"_spr; + message = fmt::format("{} is incompatible with this version of Geode", cause); + m_longMessage = problem.message; + break; } m_problem = std::move(problem); diff --git a/loader/src/utils/VersionInfo.cpp b/loader/src/utils/VersionInfo.cpp index 885a1e91..40a28e89 100644 --- a/loader/src/utils/VersionInfo.cpp +++ b/loader/src/utils/VersionInfo.cpp @@ -182,3 +182,62 @@ std::string ComparableVersionInfo::toString() const { std::string geode::format_as(ComparableVersionInfo const& version) { return version.toString(); } + +bool geode::semverCompare(VersionInfo const& current, VersionInfo const& target) { + if (target.getMajor() != current.getMajor()) { + return false; + } + if (target.getMinor() > current.getMinor()) { + return false; + } + auto ct = current.getTag(); + auto tt = target.getTag(); + if (ct && tt) { + auto currentTag = ct.value(); + auto targetTag = tt.value(); + switch (targetTag.value) { + case VersionTag::Alpha: + if (currentTag.value > VersionTag::Alpha) { + return false; + } + if (currentTag.number && targetTag.number) { + return currentTag.number.value() == targetTag.number.value(); + } + if (currentTag.number) { + return true; + } + if (targetTag.number) { + return false; + } + return true; + case VersionTag::Beta: + if (currentTag.number && targetTag.number) { + return currentTag.number.value() >= targetTag.number.value(); + } + if (currentTag.number) { + return true; + } + if (targetTag.number) { + return false; + } + return true; + default: + return true; + } + } + else if (ct) { + auto currentTag = ct.value(); + if (currentTag.value > VersionTag::Alpha) { + return true; + } + return false; + } + else if (tt) { + auto targetTag = tt.value(); + if (targetTag.value > VersionTag::Alpha) { + return true; + } + return false; + } + return true; +} diff --git a/loader/test/dependency/mod.json b/loader/test/dependency/mod.json index 00ee7276..bfb95961 100644 --- a/loader/test/dependency/mod.json +++ b/loader/test/dependency/mod.json @@ -1,6 +1,6 @@ { "geode": "2.0.0", - "gd": "*", + "gd": "*", "version": "1.0.0", "id": "geode.testdep", "name": "Geode Test Dependency",