geode/loader/src/hooks/LoadingLayer.cpp

228 lines
7.6 KiB
C++
Raw Normal View History

2022-10-30 14:56:36 -04:00
#include <Geode/modify/LoadingLayer.hpp>
2024-01-12 14:18:24 -05:00
#include <Geode/modify/CCLayer.hpp>
#include <Geode/utils/cocos.hpp>
2022-12-10 11:30:14 -05:00
#include <array>
#include <fmt/format.h>
#include <loader/LoaderImpl.hpp>
using namespace geode::prelude;
struct CustomLoadingLayer : Modify<CustomLoadingLayer, LoadingLayer> {
CCLabelBMFont* m_smallLabel = nullptr;
CCLabelBMFont* m_smallLabel2 = nullptr;
int m_geodeLoadStep = 0;
int m_totalMods = 0;
2024-01-12 14:18:24 -05:00
static void onModify(const auto& self) {
if (!Loader::get()->isForwardCompatMode())
return;
log::warn("Switching to fallback custom loading layer in forward compat");
for (const auto& [_, hook] : self.m_hooks) {
hook->setAutoEnable(false);
}
}
void updateLoadedModsLabel() {
2023-08-09 11:55:14 -04:00
auto allMods = Loader::get()->getAllMods();
auto count = std::count_if(allMods.begin(), allMods.end(), [&](auto& item) {
2023-09-11 07:38:14 -04:00
return item->isEnabled();
2023-08-09 11:55:14 -04:00
});
2023-12-21 23:45:43 -05:00
auto str = fmt::format("Geode: Loaded {}/{} mods", count, m_fields->m_totalMods);
this->setSmallText(str);
auto currentMod = LoaderImpl::get()->m_currentlyLoadingMod;
auto modName = currentMod ? currentMod->getName() : "Unknown";
this->setSmallText2(modName);
2023-08-09 11:55:14 -04:00
}
void setSmallText(std::string const& text) {
m_fields->m_smallLabel->setString(text.c_str());
}
void setSmallText2(std::string const& text) {
m_fields->m_smallLabel2->setString(text.c_str());
}
// hook
2023-08-09 11:55:14 -04:00
bool init(bool fromReload) {
2023-09-16 12:03:31 -04:00
CCFileUtils::get()->updatePaths();
if (!LoadingLayer::init(fromReload)) return false;
2023-08-09 11:55:14 -04:00
2023-12-21 23:45:43 -05:00
m_fields->m_totalMods = Loader::get()->getAllMods().size();
2023-08-09 11:55:14 -04:00
auto winSize = CCDirector::sharedDirector()->getWinSize();
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);
2023-08-09 11:55:14 -04:00
m_fields->m_smallLabel2 = CCLabelBMFont::create("", "goldFont.fnt");
m_fields->m_smallLabel2->setPosition(winSize.width / 2, 15.f);
m_fields->m_smallLabel2->setScale(.45f);
m_fields->m_smallLabel2->setID("geode-small-label");
this->addChild(m_fields->m_smallLabel2);
return true;
}
2023-08-09 11:55:14 -04:00
void setupLoadingMods() {
if (Loader::get()->getLoadingState() != Loader::LoadingState::Done) {
this->updateLoadedModsLabel();
this->waitLoadAssets();
}
else {
this->continueLoadAssets();
this->setSmallText2("");
}
}
void setupLoaderResources() {
log::debug("Verifying Loader Resources");
this->setSmallText("Verifying Loader Resources");
2023-08-09 11:55:14 -04:00
// verify loader resources
Loader::get()->queueInMainThread([&]() {
if (!LoaderImpl::get()->verifyLoaderResources()) {
log::debug("Downloading Loader Resources");
this->setSmallText("Downloading Loader Resources");
this->addChild(EventListenerNode<ResourceDownloadFilter>::create(
this, &CustomLoadingLayer::updateResourcesProgress
));
}
else {
log::debug("Loading Loader Resources");
this->setSmallText("Loading Loader Resources");
LoaderImpl::get()->updateSpecialFiles();
this->continueLoadAssets();
}
});
}
void updateResourcesProgress(ResourceDownloadEvent* event) {
std::visit(makeVisitor {
[&](UpdateProgress const& progress) {
this->setSmallText(fmt::format(
"Downloading Loader Resources: {}%", progress.first
));
},
[&](UpdateFinished) {
2023-10-01 12:41:25 -04:00
log::debug("Downloaded Loader Resources");
this->setSmallText("Downloaded Loader Resources");
this->continueLoadAssets();
},
2022-12-09 05:53:49 -05:00
[&](UpdateFailed const& error) {
2023-10-01 12:41:25 -04:00
log::debug("Failed Loader Resources");
LoaderImpl::get()->platformMessageBox(
"Error updating resources",
error + ".\n"
"You will have to install resources manually by downloading resources.zip "
"from the latest release on GitHub: "
"https://github.com/geode-sdk/geode/releases/latest.\n"
"The game will be loaded as normal, but please be aware "
"that it is very likely to crash. "
);
this->setSmallText("Failed Loader Resources");
this->continueLoadAssets();
}
}, event->status);
}
void setupModResources() {
log::debug("Loading mod resources");
this->setSmallText("Loading mod resources");
2024-01-12 16:49:42 -05:00
LoaderImpl::get()->updateResources(true);
this->continueLoadAssets();
}
int getCurrentStep() {
return m_fields->m_geodeLoadStep + m_loadStep + 1 + LoaderImpl::get()->m_refreshedModCount;
}
int getTotalStep() {
2023-12-21 23:45:43 -05:00
return 18 + m_fields->m_totalMods;
}
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();
2023-08-09 11:55:14 -04:00
}
return !m_fromRefresh;
}
2024-01-12 14:18:24 -05:00
// hook
2024-01-12 14:18:24 -05:00
void loadAssets() {
2023-10-01 08:23:48 -04:00
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;
}
this->updateLoadingBar();
}
};
2024-01-12 14:18:24 -05:00
struct FallbackCustomLoadingLayer : Modify<FallbackCustomLoadingLayer, CCLayer> {
static void onModify(const auto& self) {
if (Loader::get()->isForwardCompatMode())
return;
for (const auto& [_, hook] : self.m_hooks) {
hook->setAutoEnable(false);
}
}
bool init() {
if (!CCLayer::init())
return false;
if (!typeinfo_cast<LoadingLayer*>(this))
return true;
auto winSize = CCDirector::sharedDirector()->getWinSize();
auto label = CCLabelBMFont::create(
"Loading Geode without UI, see console for details.",
"goldFont.fnt"
);
label->setPosition(winSize.width / 2, 30.f);
label->setScale(.45f);
label->setZOrder(99);
label->setID("geode-small-label");
this->addChild(label);
// TODO: verify loader resources on fallback?
2024-01-12 16:49:42 -05:00
LoaderImpl::get()->updateResources(true);
2024-01-12 14:18:24 -05:00
return true;
}
};