mirror of
https://github.com/geode-sdk/geode.git
synced 2024-11-23 07:57:51 -05:00
Merge branch 'main' of https://github.com/geode-sdk/geode into main
This commit is contained in:
commit
3802af1e70
5 changed files with 109 additions and 26 deletions
|
@ -28,6 +28,7 @@ namespace geode {
|
||||||
Suggestion,
|
Suggestion,
|
||||||
Recommendation,
|
Recommendation,
|
||||||
Conflict,
|
Conflict,
|
||||||
|
OutdatedConflict,
|
||||||
InvalidFile,
|
InvalidFile,
|
||||||
Duplicate,
|
Duplicate,
|
||||||
SetupFailed,
|
SetupFailed,
|
||||||
|
@ -38,6 +39,10 @@ namespace geode {
|
||||||
UnzipFailed,
|
UnzipFailed,
|
||||||
UnsupportedVersion,
|
UnsupportedVersion,
|
||||||
UnsupportedGeodeVersion,
|
UnsupportedGeodeVersion,
|
||||||
|
NeedsNewerGeodeVersion,
|
||||||
|
DisabledDependency,
|
||||||
|
OutdatedDependency,
|
||||||
|
OutdatedIncompatibility,
|
||||||
};
|
};
|
||||||
Type type;
|
Type type;
|
||||||
std::variant<ghc::filesystem::path, ModMetadata, Mod*> cause;
|
std::variant<ghc::filesystem::path, ModMetadata, Mod*> cause;
|
||||||
|
|
|
@ -16,6 +16,14 @@ namespace geode {
|
||||||
Any
|
Any
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class VersionCompareResult {
|
||||||
|
TooOld,
|
||||||
|
Match,
|
||||||
|
TooNew,
|
||||||
|
MajorMismatch,
|
||||||
|
GenericMismatch
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A version label, like v1.0.0-alpha or v2.3.4-prerelease. Limited to these
|
* A version label, like v1.0.0-alpha or v2.3.4-prerelease. Limited to these
|
||||||
* options; arbitary identifiers are not supported. Additional numbering
|
* options; arbitary identifiers are not supported. Additional numbering
|
||||||
|
@ -198,30 +206,35 @@ namespace geode {
|
||||||
static Result<ComparableVersionInfo> parse(std::string const& string);
|
static Result<ComparableVersionInfo> parse(std::string const& string);
|
||||||
|
|
||||||
constexpr bool compare(VersionInfo const& version) const {
|
constexpr bool compare(VersionInfo const& version) const {
|
||||||
|
return compareWithReason(version) == VersionCompareResult::Match;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr VersionCompareResult compareWithReason(VersionInfo const& version) const {
|
||||||
if (m_compare == VersionCompare::Any) {
|
if (m_compare == VersionCompare::Any) {
|
||||||
return true;
|
return VersionCompareResult::Match;
|
||||||
}
|
}
|
||||||
|
|
||||||
// opposing major versions never match
|
// opposing major versions never match
|
||||||
if (m_version.getMajor() != version.getMajor()) {
|
if (m_version.getMajor() != version.getMajor()) {
|
||||||
return false;
|
return VersionCompareResult::MajorMismatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
// the comparison works invertedly as a version like "v1.2.0"
|
// the comparison works invertedly as a version like "v1.2.0"
|
||||||
// should return true for "<=v1.3.0"
|
// should return true for "<=v1.3.0"
|
||||||
switch (m_compare) {
|
switch (m_compare) {
|
||||||
case VersionCompare::LessEq:
|
case VersionCompare::LessEq:
|
||||||
return version <= m_version;
|
return version <= m_version ? VersionCompareResult::Match : VersionCompareResult::TooNew;
|
||||||
case VersionCompare::MoreEq:
|
case VersionCompare::MoreEq:
|
||||||
return version >= m_version;
|
return version >= m_version ? VersionCompareResult::Match : VersionCompareResult::TooOld;
|
||||||
case VersionCompare::Less:
|
case VersionCompare::Less:
|
||||||
return version < m_version;
|
return version < m_version ? VersionCompareResult::Match : VersionCompareResult::TooNew;
|
||||||
case VersionCompare::More:
|
case VersionCompare::More:
|
||||||
return version > m_version;
|
return version > m_version ? VersionCompareResult::Match : VersionCompareResult::TooOld;
|
||||||
case VersionCompare::Exact:
|
case VersionCompare::Exact:
|
||||||
return version == m_version;
|
return version == m_version ? VersionCompareResult::Match :
|
||||||
|
(version > m_version) ? VersionCompareResult::TooOld : VersionCompareResult::TooNew;
|
||||||
default:
|
default:
|
||||||
return false;
|
return VersionCompareResult::GenericMismatch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -443,7 +443,7 @@ void Loader::Impl::loadModGraph(Mod* node, bool early) {
|
||||||
node,
|
node,
|
||||||
res.unwrapErr()
|
res.unwrapErr()
|
||||||
});
|
});
|
||||||
log::error("Unsupported game version: {}", res.unwrapErr());
|
log::error("Geometry Dash version {} is required to run this mod", res.unwrapErr());
|
||||||
m_refreshingModCount -= 1;
|
m_refreshingModCount -= 1;
|
||||||
log::popNest();
|
log::popNest();
|
||||||
return;
|
return;
|
||||||
|
@ -451,10 +451,10 @@ void Loader::Impl::loadModGraph(Mod* node, bool early) {
|
||||||
|
|
||||||
if (!this->isModVersionSupported(node->getMetadata().getGeodeVersion())) {
|
if (!this->isModVersionSupported(node->getMetadata().getGeodeVersion())) {
|
||||||
this->addProblem({
|
this->addProblem({
|
||||||
LoadProblem::Type::UnsupportedGeodeVersion,
|
node->getMetadata().getGeodeVersion() > this->getVersion() ? LoadProblem::Type::NeedsNewerGeodeVersion : LoadProblem::Type::UnsupportedGeodeVersion,
|
||||||
node,
|
node,
|
||||||
fmt::format(
|
fmt::format(
|
||||||
"Geode version {} is not supported (current: {})",
|
"Geode version {}\nis required to run this mod\n(installed: {})",
|
||||||
node->getMetadata().getGeodeVersion().toString(),
|
node->getMetadata().getGeodeVersion().toString(),
|
||||||
this->getVersion().toString()
|
this->getVersion().toString()
|
||||||
)
|
)
|
||||||
|
@ -539,13 +539,44 @@ void Loader::Impl::findProblems() {
|
||||||
log::warn("{} recommends {} {}", id, dep.id, dep.version);
|
log::warn("{} recommends {} {}", id, dep.id, dep.version);
|
||||||
break;
|
break;
|
||||||
case ModMetadata::Dependency::Importance::Required:
|
case ModMetadata::Dependency::Importance::Required:
|
||||||
this->addProblem({
|
if(m_mods.find(dep.id) == m_mods.end()) {
|
||||||
LoadProblem::Type::MissingDependency,
|
this->addProblem({
|
||||||
mod,
|
LoadProblem::Type::MissingDependency,
|
||||||
fmt::format("{} {}", dep.id, dep.version.toString())
|
mod,
|
||||||
});
|
fmt::format("{}", dep.id)
|
||||||
log::error("{} requires {} {}", id, dep.id, dep.version);
|
});
|
||||||
break;
|
log::error("{} requires {} {}", id, dep.id, dep.version);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
auto installedDependency = m_mods.at(dep.id);
|
||||||
|
|
||||||
|
if(!installedDependency->isEnabled()) {
|
||||||
|
this->addProblem({
|
||||||
|
LoadProblem::Type::DisabledDependency,
|
||||||
|
mod,
|
||||||
|
fmt::format("{}", dep.id)
|
||||||
|
});
|
||||||
|
log::error("{} requires {} {}", id, dep.id, dep.version);
|
||||||
|
break;
|
||||||
|
} else if(dep.version.compareWithReason(installedDependency->getVersion()) == VersionCompareResult::TooOld) {
|
||||||
|
this->addProblem({
|
||||||
|
LoadProblem::Type::OutdatedDependency,
|
||||||
|
mod,
|
||||||
|
fmt::format("{}", dep.id)
|
||||||
|
});
|
||||||
|
log::error("{} requires {} {}", id, dep.id, dep.version);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
// fires on major mismatch or too new version of dependency
|
||||||
|
this->addProblem({
|
||||||
|
LoadProblem::Type::MissingDependency,
|
||||||
|
mod,
|
||||||
|
fmt::format("{} {}", dep.id, dep.version)
|
||||||
|
});
|
||||||
|
log::error("{} requires {} {}", id, dep.id, dep.version);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -555,18 +586,18 @@ void Loader::Impl::findProblems() {
|
||||||
switch(dep.importance) {
|
switch(dep.importance) {
|
||||||
case ModMetadata::Incompatibility::Importance::Conflicting: {
|
case ModMetadata::Incompatibility::Importance::Conflicting: {
|
||||||
this->addProblem({
|
this->addProblem({
|
||||||
LoadProblem::Type::Conflict,
|
dep.version.toString()[0] == '<' ? LoadProblem::Type::OutdatedConflict : LoadProblem::Type::Conflict,
|
||||||
mod,
|
mod,
|
||||||
fmt::format("{} {}", dep.id, dep.version.toString())
|
fmt::format("{}", dep.id)
|
||||||
});
|
});
|
||||||
log::warn("{} conflicts with {} {}", id, dep.id, dep.version);
|
log::warn("{} conflicts with {} {}", id, dep.id, dep.version);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case ModMetadata::Incompatibility::Importance::Breaking: {
|
case ModMetadata::Incompatibility::Importance::Breaking: {
|
||||||
this->addProblem({
|
this->addProblem({
|
||||||
LoadProblem::Type::PresentIncompatibility,
|
dep.version.toString()[0] == '<' ? LoadProblem::Type::OutdatedIncompatibility : LoadProblem::Type::PresentIncompatibility,
|
||||||
mod,
|
mod,
|
||||||
fmt::format("{} {}", dep.id, dep.version.toString())
|
fmt::format("{}", dep.id)
|
||||||
});
|
});
|
||||||
log::error("{} breaks {} {}", id, dep.id, dep.version);
|
log::error("{} breaks {} {}", id, dep.id, dep.version);
|
||||||
} break;
|
} break;
|
||||||
|
@ -575,7 +606,7 @@ void Loader::Impl::findProblems() {
|
||||||
this->addProblem({
|
this->addProblem({
|
||||||
LoadProblem::Type::PresentIncompatibility,
|
LoadProblem::Type::PresentIncompatibility,
|
||||||
mod,
|
mod,
|
||||||
fmt::format("{} {}", dep.id, dep.version.toString())
|
fmt::format("{}", dep.id)
|
||||||
});
|
});
|
||||||
log::error("{} supersedes {} {}", id, dep.id, dep.version);
|
log::error("{} supersedes {} {}", id, dep.id, dep.version);
|
||||||
} break;
|
} break;
|
||||||
|
|
|
@ -54,8 +54,16 @@ bool ProblemsListCell::init(LoadProblem problem, ProblemsListPopup* list, CCSize
|
||||||
message = fmt::format("{} recommends {}", cause, problem.message);
|
message = fmt::format("{} recommends {}", cause, problem.message);
|
||||||
break;
|
break;
|
||||||
case LoadProblem::Type::Conflict:
|
case LoadProblem::Type::Conflict:
|
||||||
|
// i copy pasted the message from incompatibility
|
||||||
|
// because as far as i can tell there's no behavorial
|
||||||
|
// difference, so it makes no sense to show the difference
|
||||||
|
// to the user
|
||||||
icon = "info-warning.png"_spr;
|
icon = "info-warning.png"_spr;
|
||||||
message = fmt::format("{} conflicts with {}", cause, problem.message);
|
message = fmt::format("Uninstall {} to use {}", problem.message, cause);
|
||||||
|
break;
|
||||||
|
case LoadProblem::Type::OutdatedConflict:
|
||||||
|
icon = "info-alert.png"_spr;
|
||||||
|
message = fmt::format("Update {} to use {}", problem.message, cause);
|
||||||
break;
|
break;
|
||||||
case LoadProblem::Type::InvalidFile:
|
case LoadProblem::Type::InvalidFile:
|
||||||
icon = "info-alert.png"_spr;
|
icon = "info-alert.png"_spr;
|
||||||
|
@ -84,11 +92,23 @@ bool ProblemsListCell::init(LoadProblem problem, ProblemsListPopup* list, CCSize
|
||||||
break;
|
break;
|
||||||
case LoadProblem::Type::MissingDependency:
|
case LoadProblem::Type::MissingDependency:
|
||||||
icon = "info-alert.png"_spr;
|
icon = "info-alert.png"_spr;
|
||||||
message = fmt::format("{} depends on {}", cause, problem.message);
|
message = fmt::format("Install {} to use {}", problem.message, cause);
|
||||||
|
break;
|
||||||
|
case LoadProblem::Type::DisabledDependency:
|
||||||
|
icon = "info-alert.png"_spr;
|
||||||
|
message = fmt::format("Enable {} to use {}", problem.message, cause);
|
||||||
|
break;
|
||||||
|
case LoadProblem::Type::OutdatedDependency:
|
||||||
|
icon = "info-alert.png"_spr;
|
||||||
|
message = fmt::format("Update {} to use {}", problem.message, cause);
|
||||||
break;
|
break;
|
||||||
case LoadProblem::Type::PresentIncompatibility:
|
case LoadProblem::Type::PresentIncompatibility:
|
||||||
icon = "info-alert.png"_spr;
|
icon = "info-alert.png"_spr;
|
||||||
message = fmt::format("{} is incompatible with {}", cause, problem.message);
|
message = fmt::format("Uninstall {} to use {}", problem.message, cause);
|
||||||
|
break;
|
||||||
|
case LoadProblem::Type::OutdatedIncompatibility:
|
||||||
|
icon = "info-alert.png"_spr;
|
||||||
|
message = fmt::format("Update {} to use {}", problem.message, cause);
|
||||||
break;
|
break;
|
||||||
case LoadProblem::Type::UnzipFailed:
|
case LoadProblem::Type::UnzipFailed:
|
||||||
icon = "info-alert.png"_spr;
|
icon = "info-alert.png"_spr;
|
||||||
|
@ -105,6 +125,11 @@ bool ProblemsListCell::init(LoadProblem problem, ProblemsListPopup* list, CCSize
|
||||||
message = fmt::format("{} is incompatible with this version of Geode", cause);
|
message = fmt::format("{} is incompatible with this version of Geode", cause);
|
||||||
m_longMessage = problem.message;
|
m_longMessage = problem.message;
|
||||||
break;
|
break;
|
||||||
|
case LoadProblem::Type::NeedsNewerGeodeVersion:
|
||||||
|
icon = "info-alert.png"_spr;
|
||||||
|
message = fmt::format("Update Geode to use {}", cause);
|
||||||
|
m_longMessage = problem.message;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_problem = std::move(problem);
|
m_problem = std::move(problem);
|
||||||
|
|
|
@ -38,6 +38,7 @@ void ProblemsListPopup::createList(Mod* scrollTo) {
|
||||||
}
|
}
|
||||||
|
|
||||||
CCArray* ProblemsListPopup::createCells(Mod* scrollTo, float& scrollValue) {
|
CCArray* ProblemsListPopup::createCells(Mod* scrollTo, float& scrollValue) {
|
||||||
|
std::vector<ProblemsListCell*> veryTop;
|
||||||
std::vector<ProblemsListCell*> top;
|
std::vector<ProblemsListCell*> top;
|
||||||
std::vector<ProblemsListCell*> middle;
|
std::vector<ProblemsListCell*> middle;
|
||||||
std::vector<ProblemsListCell*> bottom;
|
std::vector<ProblemsListCell*> bottom;
|
||||||
|
@ -50,6 +51,10 @@ CCArray* ProblemsListPopup::createCells(Mod* scrollTo, float& scrollValue) {
|
||||||
case geode::LoadProblem::Type::Recommendation:
|
case geode::LoadProblem::Type::Recommendation:
|
||||||
middle.push_back(ProblemsListCell::create(problem, this, this->getCellSize()));
|
middle.push_back(ProblemsListCell::create(problem, this, this->getCellSize()));
|
||||||
break;
|
break;
|
||||||
|
case geode::LoadProblem::Type::OutdatedIncompatibility:
|
||||||
|
case geode::LoadProblem::Type::PresentIncompatibility:
|
||||||
|
veryTop.push_back(ProblemsListCell::create(problem, this, this->getCellSize()));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
top.push_back(ProblemsListCell::create(problem, this, this->getCellSize()));
|
top.push_back(ProblemsListCell::create(problem, this, this->getCellSize()));
|
||||||
break;
|
break;
|
||||||
|
@ -69,6 +74,10 @@ CCArray* ProblemsListPopup::createCells(Mod* scrollTo, float& scrollValue) {
|
||||||
scrollFound = true;
|
scrollFound = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
for (auto const& item : veryTop) {
|
||||||
|
tryFindScroll(item);
|
||||||
|
final->addObject(item);
|
||||||
|
}
|
||||||
for (auto const& item : top) {
|
for (auto const& item : top) {
|
||||||
tryFindScroll(item);
|
tryFindScroll(item);
|
||||||
final->addObject(item);
|
final->addObject(item);
|
||||||
|
|
Loading…
Reference in a new issue