mirror of
https://github.com/geode-sdk/geode.git
synced 2024-11-22 07:27:59 -05:00
show outdated mods in the UI + make outdated Geode ver count for that too
This commit is contained in:
parent
f5f336532f
commit
09fa872781
12 changed files with 134 additions and 66 deletions
|
@ -46,6 +46,21 @@ namespace geode {
|
||||||
Type type;
|
Type type;
|
||||||
std::variant<std::filesystem::path, ModMetadata, Mod*> cause;
|
std::variant<std::filesystem::path, ModMetadata, Mod*> cause;
|
||||||
std::string message;
|
std::string message;
|
||||||
|
|
||||||
|
bool isSuggestion() const {
|
||||||
|
return
|
||||||
|
type == LoadProblem::Type::Recommendation ||
|
||||||
|
type == LoadProblem::Type::Suggestion;
|
||||||
|
}
|
||||||
|
bool isOutdated() const {
|
||||||
|
return
|
||||||
|
type == LoadProblem::Type::UnsupportedVersion ||
|
||||||
|
type == LoadProblem::Type::NeedsNewerGeodeVersion ||
|
||||||
|
type == LoadProblem::Type::UnsupportedGeodeVersion;
|
||||||
|
}
|
||||||
|
bool isProblem() const {
|
||||||
|
return !isSuggestion() && !isOutdated();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class LoaderImpl;
|
class LoaderImpl;
|
||||||
|
|
|
@ -446,7 +446,16 @@ namespace geode {
|
||||||
bool isLoggingEnabled() const;
|
bool isLoggingEnabled() const;
|
||||||
void setLoggingEnabled(bool enabled);
|
void setLoggingEnabled(bool enabled);
|
||||||
|
|
||||||
bool targetsOutdatedGDVersion() const;
|
/**
|
||||||
|
* If this mod is built for an outdated GD or Geode version, returns the
|
||||||
|
* `LoadProblem` describing the situation. Otherwise `nullopt` if the
|
||||||
|
* mod is made for the correct version of the game and Geode
|
||||||
|
*/
|
||||||
|
std::optional<LoadProblem> targetsOutdatedVersion() const;
|
||||||
|
/**
|
||||||
|
* @note Make sure to also call `targetsOutdatedVersion` if you want to
|
||||||
|
* make sure the mod is actually loadable
|
||||||
|
*/
|
||||||
bool hasLoadProblems() const;
|
bool hasLoadProblems() const;
|
||||||
std::vector<LoadProblem> getAllProblems() const;
|
std::vector<LoadProblem> getAllProblems() const;
|
||||||
std::vector<LoadProblem> getProblems() const;
|
std::vector<LoadProblem> getProblems() const;
|
||||||
|
|
|
@ -46,7 +46,7 @@ void crashlog::printMods(std::stringstream& stream) {
|
||||||
mod->isCurrentlyLoading() ? "o"sv :
|
mod->isCurrentlyLoading() ? "o"sv :
|
||||||
mod->isEnabled() ? "x"sv :
|
mod->isEnabled() ? "x"sv :
|
||||||
mod->hasLoadProblems() ? "!"sv : // thank you for this bug report
|
mod->hasLoadProblems() ? "!"sv : // thank you for this bug report
|
||||||
mod->targetsOutdatedGDVersion() ? "*"sv : // thank you very much for this bug report
|
mod->targetsOutdatedVersion() ? "*"sv : // thank you very much for this bug report
|
||||||
mod->shouldLoad() ? "~"sv :
|
mod->shouldLoad() ? "~"sv :
|
||||||
" "sv,
|
" "sv,
|
||||||
mod->getVersion().toVString(), mod->getID()
|
mod->getVersion().toVString(), mod->getID()
|
||||||
|
|
|
@ -71,11 +71,7 @@ std::vector<LoadProblem> Loader::getAllProblems() const {
|
||||||
std::vector<LoadProblem> Loader::getLoadProblems() const {
|
std::vector<LoadProblem> Loader::getLoadProblems() const {
|
||||||
std::vector<LoadProblem> result;
|
std::vector<LoadProblem> result;
|
||||||
for (auto problem : this->getAllProblems()) {
|
for (auto problem : this->getAllProblems()) {
|
||||||
if (
|
if (problem.isProblem()) {
|
||||||
problem.type != LoadProblem::Type::Recommendation &&
|
|
||||||
problem.type != LoadProblem::Type::Suggestion &&
|
|
||||||
problem.type != LoadProblem::Type::UnsupportedVersion
|
|
||||||
) {
|
|
||||||
result.push_back(problem);
|
result.push_back(problem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,7 +80,7 @@ std::vector<LoadProblem> Loader::getLoadProblems() const {
|
||||||
std::vector<LoadProblem> Loader::getOutdated() const {
|
std::vector<LoadProblem> Loader::getOutdated() const {
|
||||||
std::vector<LoadProblem> result;
|
std::vector<LoadProblem> result;
|
||||||
for (auto problem : this->getAllProblems()) {
|
for (auto problem : this->getAllProblems()) {
|
||||||
if (problem.type == LoadProblem::Type::UnsupportedVersion) {
|
if (problem.isOutdated()) {
|
||||||
result.push_back(problem);
|
result.push_back(problem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -93,10 +89,7 @@ std::vector<LoadProblem> Loader::getOutdated() const {
|
||||||
std::vector<LoadProblem> Loader::getRecommendations() const {
|
std::vector<LoadProblem> Loader::getRecommendations() const {
|
||||||
std::vector<LoadProblem> result;
|
std::vector<LoadProblem> result;
|
||||||
for (auto problem : this->getAllProblems()) {
|
for (auto problem : this->getAllProblems()) {
|
||||||
if (
|
if (problem.isSuggestion()) {
|
||||||
problem.type == LoadProblem::Type::Recommendation ||
|
|
||||||
problem.type == LoadProblem::Type::Suggestion
|
|
||||||
) {
|
|
||||||
result.push_back(problem);
|
result.push_back(problem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -384,6 +384,37 @@ void Loader::Impl::buildModGraph() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Loader::Impl::loadModGraph(Mod* node, bool early) {
|
void Loader::Impl::loadModGraph(Mod* node, bool early) {
|
||||||
|
// Check version first, as it's not worth trying to load a mod with an
|
||||||
|
// invalid target version
|
||||||
|
// Also this makes it so that when GD updates, outdated mods get shown as
|
||||||
|
// "Outdated" in the UI instead of "Missing Dependencies"
|
||||||
|
auto res = node->getMetadata().checkGameVersion();
|
||||||
|
if (!res) {
|
||||||
|
this->addProblem({
|
||||||
|
LoadProblem::Type::UnsupportedVersion,
|
||||||
|
node,
|
||||||
|
res.unwrapErr()
|
||||||
|
});
|
||||||
|
log::error("{}", res.unwrapErr());
|
||||||
|
log::popNest();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this->isModVersionSupported(node->getMetadata().getGeodeVersion())) {
|
||||||
|
this->addProblem({
|
||||||
|
node->getMetadata().getGeodeVersion() > this->getVersion() ? LoadProblem::Type::NeedsNewerGeodeVersion : LoadProblem::Type::UnsupportedGeodeVersion,
|
||||||
|
node,
|
||||||
|
fmt::format(
|
||||||
|
"Geode version {}\nis required to run this mod\n(installed: {})",
|
||||||
|
node->getMetadata().getGeodeVersion().toVString(),
|
||||||
|
this->getVersion().toVString()
|
||||||
|
)
|
||||||
|
});
|
||||||
|
log::error("Unsupported Geode version: {}", node->getMetadata().getGeodeVersion());
|
||||||
|
log::popNest();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (node->hasUnresolvedDependencies()) {
|
if (node->hasUnresolvedDependencies()) {
|
||||||
log::debug("{} {} has unresolved dependencies", node->getID(), node->getVersion());
|
log::debug("{} {} has unresolved dependencies", node->getID(), node->getVersion());
|
||||||
return;
|
return;
|
||||||
|
@ -444,35 +475,6 @@ void Loader::Impl::loadModGraph(Mod* node, bool early) {
|
||||||
log::popNest();
|
log::popNest();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto res = node->getMetadata().checkGameVersion();
|
|
||||||
if (!res) {
|
|
||||||
this->addProblem({
|
|
||||||
LoadProblem::Type::UnsupportedVersion,
|
|
||||||
node,
|
|
||||||
res.unwrapErr()
|
|
||||||
});
|
|
||||||
log::error("{}", res.unwrapErr());
|
|
||||||
m_refreshingModCount -= 1;
|
|
||||||
log::popNest();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this->isModVersionSupported(node->getMetadata().getGeodeVersion())) {
|
|
||||||
this->addProblem({
|
|
||||||
node->getMetadata().getGeodeVersion() > this->getVersion() ? LoadProblem::Type::NeedsNewerGeodeVersion : LoadProblem::Type::UnsupportedGeodeVersion,
|
|
||||||
node,
|
|
||||||
fmt::format(
|
|
||||||
"Geode version {}\nis required to run this mod\n(installed: {})",
|
|
||||||
node->getMetadata().getGeodeVersion().toVString(),
|
|
||||||
this->getVersion().toVString()
|
|
||||||
)
|
|
||||||
});
|
|
||||||
log::error("Unsupported Geode version: {}", node->getMetadata().getGeodeVersion());
|
|
||||||
m_refreshingModCount -= 1;
|
|
||||||
log::popNest();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (early) {
|
if (early) {
|
||||||
|
@ -524,6 +526,10 @@ void Loader::Impl::findProblems() {
|
||||||
log::debug("{} is not enabled", id);
|
log::debug("{} is not enabled", id);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (mod->targetsOutdatedVersion()) {
|
||||||
|
log::debug("{} is outdated", id);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
log::debug("{}", id);
|
log::debug("{}", id);
|
||||||
log::pushNest();
|
log::pushNest();
|
||||||
|
|
||||||
|
|
|
@ -255,13 +255,13 @@ bool Mod::hasSavedValue(std::string_view key) {
|
||||||
bool Mod::hasLoadProblems() const {
|
bool Mod::hasLoadProblems() const {
|
||||||
return m_impl->hasLoadProblems();
|
return m_impl->hasLoadProblems();
|
||||||
}
|
}
|
||||||
bool Mod::targetsOutdatedGDVersion() const {
|
std::optional<LoadProblem> Mod::targetsOutdatedVersion() const {
|
||||||
for (auto problem : this->getAllProblems()) {
|
for (auto problem : this->getAllProblems()) {
|
||||||
if (problem.type == LoadProblem::Type::UnsupportedVersion) {
|
if (problem.isOutdated()) {
|
||||||
return true;
|
return problem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
std::vector<LoadProblem> Mod::getAllProblems() const {
|
std::vector<LoadProblem> Mod::getAllProblems() const {
|
||||||
return m_impl->getProblems();
|
return m_impl->getProblems();
|
||||||
|
@ -269,11 +269,7 @@ std::vector<LoadProblem> Mod::getAllProblems() const {
|
||||||
std::vector<LoadProblem> Mod::getProblems() const {
|
std::vector<LoadProblem> Mod::getProblems() const {
|
||||||
std::vector<LoadProblem> result;
|
std::vector<LoadProblem> result;
|
||||||
for (auto problem : this->getAllProblems()) {
|
for (auto problem : this->getAllProblems()) {
|
||||||
if (
|
if (problem.isProblem()) {
|
||||||
problem.type != LoadProblem::Type::Recommendation &&
|
|
||||||
problem.type != LoadProblem::Type::Suggestion &&
|
|
||||||
problem.type != LoadProblem::Type::UnsupportedVersion
|
|
||||||
) {
|
|
||||||
result.push_back(problem);
|
result.push_back(problem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -282,10 +278,7 @@ std::vector<LoadProblem> Mod::getProblems() const {
|
||||||
std::vector<LoadProblem> Mod::getRecommendations() const {
|
std::vector<LoadProblem> Mod::getRecommendations() const {
|
||||||
std::vector<LoadProblem> result;
|
std::vector<LoadProblem> result;
|
||||||
for (auto problem : this->getAllProblems()) {
|
for (auto problem : this->getAllProblems()) {
|
||||||
if (
|
if (problem.isSuggestion()) {
|
||||||
problem.type == LoadProblem::Type::Recommendation ||
|
|
||||||
problem.type == LoadProblem::Type::Suggestion
|
|
||||||
) {
|
|
||||||
result.push_back(problem);
|
result.push_back(problem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -706,11 +706,7 @@ bool Mod::Impl::isCurrentlyLoading() const {
|
||||||
|
|
||||||
bool Mod::Impl::hasLoadProblems() const {
|
bool Mod::Impl::hasLoadProblems() const {
|
||||||
for (auto const& problem : m_problems) {
|
for (auto const& problem : m_problems) {
|
||||||
if (
|
if (problem.isProblem()) {
|
||||||
problem.type != LoadProblem::Type::Recommendation &&
|
|
||||||
problem.type != LoadProblem::Type::Suggestion &&
|
|
||||||
problem.type != LoadProblem::Type::UnsupportedVersion
|
|
||||||
) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,8 @@ $on_mod(Loaded) {
|
||||||
ColorProvider::get()->define("mod-list-version-label-updates-available"_spr, ccc3(88, 202, 255));
|
ColorProvider::get()->define("mod-list-version-label-updates-available"_spr, ccc3(88, 202, 255));
|
||||||
ColorProvider::get()->define("mod-list-restart-required-label"_spr, ccc3(153, 245, 245));
|
ColorProvider::get()->define("mod-list-restart-required-label"_spr, ccc3(153, 245, 245));
|
||||||
ColorProvider::get()->define("mod-list-restart-required-label-bg"_spr, ccc3(123, 156, 163));
|
ColorProvider::get()->define("mod-list-restart-required-label-bg"_spr, ccc3(123, 156, 163));
|
||||||
|
ColorProvider::get()->define("mod-list-outdated-label"_spr, ccc3(245, 153, 245));
|
||||||
|
ColorProvider::get()->define("mod-list-outdated-label-bg"_spr, ccc3(156, 123, 163));
|
||||||
ColorProvider::get()->define("mod-list-search-bg"_spr, { 83, 65, 109, 255 });
|
ColorProvider::get()->define("mod-list-search-bg"_spr, { 83, 65, 109, 255 });
|
||||||
ColorProvider::get()->define("mod-list-updates-available-bg"_spr, { 139, 89, 173, 255 });
|
ColorProvider::get()->define("mod-list-updates-available-bg"_spr, { 139, 89, 173, 255 });
|
||||||
ColorProvider::get()->define("mod-list-updates-available-bg-2"_spr, { 45, 110, 222, 255 });
|
ColorProvider::get()->define("mod-list-updates-available-bg-2"_spr, { 45, 110, 222, 255 });
|
||||||
|
|
|
@ -95,6 +95,17 @@ bool ModItem::init(ModSource&& source) {
|
||||||
m_restartRequiredLabel->setLayoutOptions(AxisLayoutOptions::create()->setScaleLimits(std::nullopt, .75f));
|
m_restartRequiredLabel->setLayoutOptions(AxisLayoutOptions::create()->setScaleLimits(std::nullopt, .75f));
|
||||||
m_infoContainer->addChild(m_restartRequiredLabel);
|
m_infoContainer->addChild(m_restartRequiredLabel);
|
||||||
|
|
||||||
|
m_outdatedLabel = createTagLabel(
|
||||||
|
fmt::format("Outdated (GD {})", m_source.getMetadata().getGameVersion().value_or("*")),
|
||||||
|
{
|
||||||
|
to3B(ColorProvider::get()->color("mod-list-outdated-label"_spr)),
|
||||||
|
to3B(ColorProvider::get()->color("mod-list-outdated-label-bg"_spr))
|
||||||
|
}
|
||||||
|
);
|
||||||
|
m_outdatedLabel->setID("outdated-label");
|
||||||
|
m_outdatedLabel->setLayoutOptions(AxisLayoutOptions::create()->setScaleLimits(std::nullopt, .75f));
|
||||||
|
m_infoContainer->addChild(m_outdatedLabel);
|
||||||
|
|
||||||
m_downloadBarContainer = CCNode::create();
|
m_downloadBarContainer = CCNode::create();
|
||||||
m_downloadBarContainer->setID("download-bar-container");
|
m_downloadBarContainer->setID("download-bar-container");
|
||||||
m_downloadBarContainer->setContentSize({ 320, 30 });
|
m_downloadBarContainer->setContentSize({ 320, 30 });
|
||||||
|
@ -185,7 +196,7 @@ bool ModItem::init(ModSource&& source) {
|
||||||
m_viewMenu->addChild(m_enableToggle);
|
m_viewMenu->addChild(m_enableToggle);
|
||||||
m_viewMenu->updateLayout();
|
m_viewMenu->updateLayout();
|
||||||
}
|
}
|
||||||
if (mod->hasLoadProblems() || mod->targetsOutdatedGDVersion()) {
|
if (mod->hasLoadProblems() || mod->targetsOutdatedVersion()) {
|
||||||
auto viewErrorSpr = createGeodeCircleButton(
|
auto viewErrorSpr = createGeodeCircleButton(
|
||||||
CCSprite::createWithSpriteFrameName("exclamation.png"_spr), 1.f,
|
CCSprite::createWithSpriteFrameName("exclamation.png"_spr), 1.f,
|
||||||
CircleBaseSize::Small
|
CircleBaseSize::Small
|
||||||
|
@ -342,7 +353,6 @@ void ModItem::updateState() {
|
||||||
m_downloadBarContainer->setVisible(false);
|
m_downloadBarContainer->setVisible(false);
|
||||||
m_downloadWaiting->setVisible(false);
|
m_downloadWaiting->setVisible(false);
|
||||||
}
|
}
|
||||||
m_infoContainer->updateLayout();
|
|
||||||
|
|
||||||
// Set default colors based on source to start off with
|
// Set default colors based on source to start off with
|
||||||
// (possibly overriding later based on state)
|
// (possibly overriding later based on state)
|
||||||
|
@ -410,16 +420,22 @@ void ModItem::updateState() {
|
||||||
m_titleContainer->updateLayout();
|
m_titleContainer->updateLayout();
|
||||||
|
|
||||||
// If there were problems, tint the BG red
|
// If there were problems, tint the BG red
|
||||||
|
m_outdatedLabel->setVisible(false);
|
||||||
if (m_source.asMod()) {
|
if (m_source.asMod()) {
|
||||||
if (m_source.asMod()->hasLoadProblems()) {
|
if (m_source.asMod()->hasLoadProblems()) {
|
||||||
m_bg->setColor("mod-list-errors-found"_cc3b);
|
m_bg->setColor("mod-list-errors-found"_cc3b);
|
||||||
m_bg->setOpacity(isGeodeTheme() ? 25 : 90);
|
m_bg->setOpacity(isGeodeTheme() ? 25 : 90);
|
||||||
}
|
}
|
||||||
if (m_source.asMod()->targetsOutdatedGDVersion()) {
|
if (m_source.asMod()->targetsOutdatedVersion()) {
|
||||||
m_bg->setOpacity(isGeodeTheme() ? 0 : 0);
|
m_bg->setColor("mod-list-outdated-label"_cc3b);
|
||||||
|
m_bg->setOpacity(isGeodeTheme() ? 25 : 90);
|
||||||
|
m_outdatedLabel->setVisible(true);
|
||||||
|
m_developers->setVisible(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_infoContainer->updateLayout();
|
||||||
|
|
||||||
// Highlight item via BG if it wants to restart for extra UI attention
|
// Highlight item via BG if it wants to restart for extra UI attention
|
||||||
if (wantsRestart) {
|
if (wantsRestart) {
|
||||||
m_bg->setColor("mod-list-restart-required-label"_cc3b);
|
m_bg->setColor("mod-list-restart-required-label"_cc3b);
|
||||||
|
@ -541,7 +557,38 @@ void ModItem::onView(CCObject*) {
|
||||||
}
|
}
|
||||||
void ModItem::onViewError(CCObject*) {
|
void ModItem::onViewError(CCObject*) {
|
||||||
if (auto mod = m_source.asMod()) {
|
if (auto mod = m_source.asMod()) {
|
||||||
ModErrorPopup::create(mod)->show();
|
if (auto problem = mod->targetsOutdatedVersion()) {
|
||||||
|
std::string issue;
|
||||||
|
std::string howToFix;
|
||||||
|
switch (problem->type) {
|
||||||
|
default:
|
||||||
|
case LoadProblem::Type::UnsupportedVersion: {
|
||||||
|
issue = fmt::format("<cy>{}</c>", problem->message);
|
||||||
|
howToFix = "wait for the developer to <cj>release an update to "
|
||||||
|
"the mod</c> that supports the newer version.";
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case LoadProblem::Type::UnsupportedGeodeVersion: {
|
||||||
|
issue = "This mod is made for a <cp>newer version of Geode</c>.";
|
||||||
|
howToFix = "<cp>update Geode</c> by enabling <co>Automatic Updates</c> "
|
||||||
|
"or redownloading it from the Geode website.";
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case LoadProblem::Type::NeedsNewerGeodeVersion: {
|
||||||
|
issue = "This mod is made for an <cy>older version of Geode</c>.";
|
||||||
|
howToFix = "wait for the developer to <cj>release an update to "
|
||||||
|
"the mod</c> that supports the newer version.";
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
FLAlertLayer::create(
|
||||||
|
"Outdated",
|
||||||
|
fmt::format("{} Please {}", issue, howToFix),
|
||||||
|
"OK"
|
||||||
|
)->show();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ModErrorPopup::create(mod)->show();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void ModItem::onEnable(CCObject*) {
|
void ModItem::onEnable(CCObject*) {
|
||||||
|
|
|
@ -25,6 +25,7 @@ protected:
|
||||||
CCNode* m_recommendedBy;
|
CCNode* m_recommendedBy;
|
||||||
CCLabelBMFont* m_developerLabel;
|
CCLabelBMFont* m_developerLabel;
|
||||||
ButtonSprite* m_restartRequiredLabel;
|
ButtonSprite* m_restartRequiredLabel;
|
||||||
|
ButtonSprite* m_outdatedLabel;
|
||||||
CCNode* m_downloadWaiting;
|
CCNode* m_downloadWaiting;
|
||||||
CCNode* m_downloadBarContainer;
|
CCNode* m_downloadBarContainer;
|
||||||
Slider* m_downloadBar;
|
Slider* m_downloadBar;
|
||||||
|
|
|
@ -13,7 +13,7 @@ bool InstalledModsQuery::preCheck(ModSource const& src) const {
|
||||||
}
|
}
|
||||||
// If only errors requested, only show mods with errors (duh)
|
// If only errors requested, only show mods with errors (duh)
|
||||||
if (type == InstalledModListType::OnlyOutdated) {
|
if (type == InstalledModListType::OnlyOutdated) {
|
||||||
return src.asMod()->targetsOutdatedGDVersion();
|
return src.asMod()->targetsOutdatedVersion().has_value();
|
||||||
}
|
}
|
||||||
if (type == InstalledModListType::OnlyErrors) {
|
if (type == InstalledModListType::OnlyErrors) {
|
||||||
return src.asMod()->hasLoadProblems();
|
return src.asMod()->hasLoadProblems();
|
||||||
|
|
|
@ -230,7 +230,13 @@ void filterModsWithLocalQuery(ModListSource::ProvidedMods& mods, Query const& qu
|
||||||
if (a.second != b.second) {
|
if (a.second != b.second) {
|
||||||
return a.second > b.second;
|
return a.second > b.second;
|
||||||
}
|
}
|
||||||
// Sort secondarily alphabetically
|
// Make sure outdated mods are always last by default
|
||||||
|
auto aIsOutdated = a.first.getMetadata().checkGameVersion().isErr();
|
||||||
|
auto bIsOutdated = b.first.getMetadata().checkGameVersion().isErr();
|
||||||
|
if (aIsOutdated != bIsOutdated) {
|
||||||
|
return !aIsOutdated;
|
||||||
|
}
|
||||||
|
// Fallback sort alphabetically
|
||||||
return utils::string::caseInsensitiveCompare(
|
return utils::string::caseInsensitiveCompare(
|
||||||
a.first.getMetadata().getName(),
|
a.first.getMetadata().getName(),
|
||||||
b.first.getMetadata().getName()
|
b.first.getMetadata().getName()
|
||||||
|
|
Loading…
Reference in a new issue