change loadinglayer, fix macos spritesheet issue, separate user disabled & problem disabled, fix not enabling a disabled mod that has dependency disabled,

This commit is contained in:
altalk23 2023-09-12 18:12:46 +03:00
parent 54ec221ece
commit ef4764728b
8 changed files with 126 additions and 67 deletions

View file

@ -406,6 +406,8 @@ namespace geode {
bool isLoggingEnabled() const;
void setLoggingEnabled(bool enabled);
bool shouldLoad() const;
friend class ModImpl;
};
}

View file

@ -8,68 +8,77 @@
using namespace geode::prelude;
struct CustomLoadingLayer : Modify<CustomLoadingLayer, LoadingLayer> {
CCLabelBMFont* m_loadedModsLabel;
bool m_updatingResources;
CustomLoadingLayer() : m_loadedModsLabel(nullptr), m_updatingResources(false) {}
CCLabelBMFont* m_smallLabel = nullptr;
int m_geodeLoadStep = 0;
void updateLoadedModsLabel() {
auto allMods = Loader::get()->getAllMods();
auto count = std::count_if(allMods.begin(), allMods.end(), [&](auto& item) {
return item->isEnabled();
});
auto str = fmt::format("Geode: Loaded {}/{} mods", count, allMods.size());
m_fields->m_loadedModsLabel->setCString(str.c_str());
auto totalCount = std::count_if(allMods.begin(), allMods.end(), [&](auto& item) {
return item->shouldLoad();
});
auto str = fmt::format("Geode: Loaded {}/{} mods", count, totalCount);
this->setSmallText(str);
}
void setSmallText(std::string const& text) {
m_fields->m_smallLabel->setString(text.c_str());
}
// hook
bool init(bool fromReload) {
CCFileUtils::get()->updatePaths();
if (!LoadingLayer::init(fromReload)) return false;
if (fromReload) return true;
auto winSize = CCDirector::sharedDirector()->getWinSize();
m_fields->m_loadedModsLabel = CCLabelBMFont::create("Geode: Loaded 0/0 mods", "goldFont.fnt");
m_fields->m_loadedModsLabel->setPosition(winSize.width / 2, 30.f);
m_fields->m_loadedModsLabel->setScale(.45f);
m_fields->m_loadedModsLabel->setID("geode-loaded-info");
this->addChild(m_fields->m_loadedModsLabel);
this->updateLoadedModsLabel();
// fields have unpredictable destructors
this->addChild(EventListenerNode<ResourceDownloadFilter>::create(
this, &CustomLoadingLayer::updateResourcesProgress
));
// verify loader resources
if (!LoaderImpl::get()->verifyLoaderResources()) {
m_fields->m_updatingResources = true;
this->setUpdateText("Downloading Resources");
}
else {
LoaderImpl::get()->updateSpecialFiles();
}
m_fields->m_smallLabel = CCLabelBMFont::create("", "goldFont.fnt");
m_fields->m_smallLabel->setPosition(winSize.width / 2, 30.f);
m_fields->m_smallLabel->setScale(.45f);
m_fields->m_smallLabel->setID("geode-small-label");
this->addChild(m_fields->m_smallLabel);
return true;
}
void setUpdateText(std::string const& text) {
m_textArea->setString(text.c_str());
void setupLoadingMods() {
if (Loader::get()->getLoadingState() != Loader::LoadingState::Done) {
this->updateLoadedModsLabel();
this->waitLoadAssets();
}
else {
this->continueLoadAssets();
}
}
void setupLoaderResources() {
// verify loader resources
if (!LoaderImpl::get()->verifyLoaderResources()) {
this->setSmallText("Downloading Loader Resources");
this->addChild(EventListenerNode<ResourceDownloadFilter>::create(
this, &CustomLoadingLayer::updateResourcesProgress
));
}
else {
this->setSmallText("Loading Loader Resources");
LoaderImpl::get()->updateSpecialFiles();
this->continueLoadAssets();
}
}
void updateResourcesProgress(ResourceDownloadEvent* event) {
std::visit(makeVisitor {
[&](UpdateProgress const& progress) {
this->setUpdateText(fmt::format(
"Downloading Resources: {}%", progress.first
this->setSmallText(fmt::format(
"Downloading Loader Resources: {}%", progress.first
));
},
[&](UpdateFinished) {
this->setUpdateText("Resources Downloaded");
m_fields->m_updatingResources = false;
this->loadAssets();
this->setSmallText("Downloaded Loader Resources");
this->continueLoadAssets();
},
[&](UpdateFailed const& error) {
LoaderImpl::get()->platformMessageBox(
@ -81,24 +90,70 @@ struct CustomLoadingLayer : Modify<CustomLoadingLayer, LoadingLayer> {
"The game will be loaded as normal, but please be aware "
"that it is very likely to crash. "
);
this->setUpdateText("Resource Download Failed");
m_fields->m_updatingResources = false;
this->loadAssets();
this->setSmallText("Failed Loader Resources");
this->continueLoadAssets();
}
}, event->status);
}
void loadAssets() {
if (Loader::get()->getLoadingState() != Loader::LoadingState::Done) {
this->updateLoadedModsLabel();
Loader::get()->queueInMainThread([this]() {
this->loadAssets();
});
return;
void setupModResources() {
log::debug("Loading mod resources");
this->setSmallText("Loading mod resources");
Loader::get()->updateResources(true);
this->continueLoadAssets();
}
int getCurrentStep() {
return m_fields->m_geodeLoadStep + m_loadStep + 1;
}
int getTotalStep() {
return 18;
}
void updateLoadingBar() {
auto length = m_sliderGrooveXPos * this->getCurrentStep() / this->getTotalStep();
m_sliderBar->setTextureRect({0, 0, length, m_sliderGrooveHeight});
}
void waitLoadAssets() {
Loader::get()->queueInMainThread([this]() {
this->loadAssets();
});
}
void continueLoadAssets() {
++m_fields->m_geodeLoadStep;
Loader::get()->queueInMainThread([this]() {
this->loadAssets();
});
}
bool skipOnRefresh() {
if (m_fromRefresh) {
this->continueLoadAssets();
}
if (m_fields->m_updatingResources) {
return;
return !m_fromRefresh;
}
// hook
void loadAssets() {
switch (m_fields->m_geodeLoadStep) {
case 0:
if (this->skipOnRefresh()) this->setupLoadingMods();
break;
case 1:
if (this->skipOnRefresh()) this->setupLoaderResources();
break;
case 2:
this->setupModResources();
break;
case 3:
default:
this->setSmallText("Loading game resources");
LoadingLayer::loadAssets();
break;
}
LoadingLayer::loadAssets();
this->updateLoadingBar();
}
};

View file

@ -1,15 +0,0 @@
#include <Geode/loader/Loader.hpp>
#include <Geode/modify/LoadingLayer.hpp>
#include <Geode/modify/GameManager.hpp>
using namespace geode::prelude;
struct ResourcesUpdate : Modify<ResourcesUpdate, LoadingLayer> {
void loadAssets() {
LoadingLayer::loadAssets();
// this is in case the user refreshes texture quality at runtime
if (m_loadStep == 10) {
Loader::get()->updateResources(true);
}
}
};

View file

@ -408,7 +408,7 @@ void Loader::Impl::loadModGraph(Mod* node, bool early) {
return;
}
if (Mod::get()->getSavedValue<bool>("should-load-" + node->getID(), true)) {
if (node->shouldLoad()) {
log::debug("Load");
auto res = node->m_impl->loadBinary();
if (!res) {
@ -432,6 +432,10 @@ void Loader::Impl::loadModGraph(Mod* node, bool early) {
void Loader::Impl::findProblems() {
for (auto const& [id, mod] : m_mods) {
if (!mod->shouldLoad()) {
log::debug("{} is not enabled", id);
continue;
}
log::debug(id);
log::pushNest();
@ -492,7 +496,7 @@ void Loader::Impl::findProblems() {
Mod* myEpicMod = mod; // clang fix
// if the mod is not loaded but there are no problems related to it
if (!mod->isEnabled() &&
Mod::get()->getSavedValue<bool>("should-load-" + mod->getID(), true) &&
mod->shouldLoad() &&
!std::any_of(m_problems.begin(), m_problems.end(), [myEpicMod](auto& item) {
return std::holds_alternative<ModMetadata>(item.cause) &&
std::get<ModMetadata>(item.cause).getID() == myEpicMod->getID() ||

View file

@ -245,3 +245,7 @@ void Mod::setLoggingEnabled(bool enabled) {
bool Mod::hasSavedValue(std::string const& key) {
return this->getSaveContainer().contains(key);
}
bool Mod::shouldLoad() const {
return m_impl->shouldLoad();
}

View file

@ -43,7 +43,9 @@ Result<> Mod::Impl::setup() {
log::warn("Unable to load data for \"{}\": {}", m_metadata.getID(), loadRes.unwrapErr());
}
if (!m_resourcesLoaded) {
LoaderImpl::get()->updateModResources(m_self);
auto searchPathRoot = dirs::getModRuntimeDir() / m_metadata.getID() / "resources";
CCFileUtils::get()->addSearchPath(searchPathRoot.string().c_str());
m_resourcesLoaded = true;
}
@ -633,6 +635,10 @@ void Mod::Impl::setLoggingEnabled(bool enabled) {
m_loggingEnabled = enabled;
}
bool Mod::Impl::shouldLoad() const {
return Mod::get()->getSavedValue<bool>("should-load-" + m_metadata.getID(), true);
}
static Result<ModMetadata> getModImplInfo() {
std::string err;
json::Value json;

View file

@ -137,6 +137,8 @@ namespace geode {
bool isLoggingEnabled() const;
void setLoggingEnabled(bool enabled);
bool shouldLoad() const;
};
class ModImpl : public Mod::Impl {

View file

@ -250,9 +250,10 @@ void ModCell::onRestart(CCObject*) {
void ModCell::updateState() {
bool unresolved = m_mod->hasUnresolvedDependencies();
bool shouldLoad = m_mod->shouldLoad();
if (m_enableToggle) {
m_enableToggle->toggle(m_mod->isEnabled());
m_enableToggle->setEnabled(!unresolved);
m_enableToggle->setEnabled(!unresolved || shouldLoad);
m_enableToggle->m_offButton->setOpacity(unresolved ? 100 : 255);
m_enableToggle->m_offButton->setColor(unresolved ? cc3x(155) : cc3x(255));
m_enableToggle->m_onButton->setOpacity(unresolved ? 100 : 255);