mirror of
https://github.com/geode-sdk/geode.git
synced 2024-11-22 23:48:08 -05:00
implement threaded unzipping and revert typeinfo cast (but its ugly)
This commit is contained in:
parent
877b644962
commit
777cf38df0
8 changed files with 133 additions and 37 deletions
|
@ -32,7 +32,8 @@ namespace geode {
|
|||
LoadFailed,
|
||||
EnableFailed,
|
||||
MissingDependency,
|
||||
PresentIncompatibility
|
||||
PresentIncompatibility,
|
||||
UnzipFailed
|
||||
};
|
||||
Type type;
|
||||
std::variant<ghc::filesystem::path, ModMetadata, Mod*> cause;
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "ItaniumCast.hpp"
|
||||
|
||||
namespace geode {
|
||||
struct PlatformInfo {
|
||||
void* m_so;
|
||||
|
@ -13,3 +11,11 @@ namespace geode {
|
|||
namespace geode::base {
|
||||
/*GEODE_NOINLINE inline*/ uintptr_t get();
|
||||
}
|
||||
|
||||
namespace geode::cast {
|
||||
template <class After, class Before>
|
||||
After typeinfo_cast(Before ptr) {
|
||||
// yall have symbols smh
|
||||
return dynamic_cast<After>(ptr);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,30 +9,38 @@ 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;
|
||||
|
||||
void updateLoadedModsLabel() {
|
||||
auto allMods = Loader::get()->getAllMods();
|
||||
auto count = std::count_if(allMods.begin(), allMods.end(), [&](auto& item) {
|
||||
return item->isEnabled();
|
||||
});
|
||||
auto totalCount = std::count_if(allMods.begin(), allMods.end(), [&](auto& item) {
|
||||
return item->shouldLoad();
|
||||
});
|
||||
auto str = fmt::format("Geode: Loaded {}/{} mods", count, totalCount);
|
||||
auto str = fmt::format("Geode: Loaded {}/{} mods", count, m_totalMods);
|
||||
this->setSmallText(str);
|
||||
auto currentMod = LoaderImpl::get()->m_currentlyLoadingMod;
|
||||
auto modName = currentMod ? currentMod->getName() : "Unknown";
|
||||
this->setSmallText2(modName);
|
||||
}
|
||||
|
||||
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
|
||||
bool init(bool fromReload) {
|
||||
CCFileUtils::get()->updatePaths();
|
||||
|
||||
if (!LoadingLayer::init(fromReload)) return false;
|
||||
|
||||
m_totalMods = Loader::get()->getAllMods().size();
|
||||
|
||||
auto winSize = CCDirector::sharedDirector()->getWinSize();
|
||||
|
||||
m_fields->m_smallLabel = CCLabelBMFont::create("", "goldFont.fnt");
|
||||
|
@ -41,6 +49,12 @@ struct CustomLoadingLayer : Modify<CustomLoadingLayer, LoadingLayer> {
|
|||
m_fields->m_smallLabel->setID("geode-small-label");
|
||||
this->addChild(m_fields->m_smallLabel);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -51,6 +65,7 @@ struct CustomLoadingLayer : Modify<CustomLoadingLayer, LoadingLayer> {
|
|||
}
|
||||
else {
|
||||
this->continueLoadAssets();
|
||||
this->setSmallText2("");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,11 +123,11 @@ struct CustomLoadingLayer : Modify<CustomLoadingLayer, LoadingLayer> {
|
|||
}
|
||||
|
||||
int getCurrentStep() {
|
||||
return m_fields->m_geodeLoadStep + m_loadStep + 1;
|
||||
return m_fields->m_geodeLoadStep + m_loadStep + 1 + LoaderImpl::get()->m_refreshedModCount;
|
||||
}
|
||||
|
||||
int getTotalStep() {
|
||||
return 18;
|
||||
return 18 + m_totalMods;
|
||||
}
|
||||
|
||||
void updateLoadingBar() {
|
||||
|
|
|
@ -388,7 +388,7 @@ void Loader::Impl::buildModGraph() {
|
|||
|
||||
void Loader::Impl::loadModGraph(Mod* node, bool early) {
|
||||
if (early && !node->needsEarlyLoad()) {
|
||||
m_modsToLoad.push(node);
|
||||
m_modsToLoad.push_back(node);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -402,32 +402,82 @@ void Loader::Impl::loadModGraph(Mod* node, bool early) {
|
|||
|
||||
if (node->isEnabled()) {
|
||||
for (auto const& dep : node->m_impl->m_dependants) {
|
||||
this->loadModGraph(dep, early);
|
||||
m_modsToLoad.push_front(dep);
|
||||
}
|
||||
log::popNest();
|
||||
return;
|
||||
}
|
||||
|
||||
if (node->shouldLoad()) {
|
||||
log::debug("Load");
|
||||
auto res = node->m_impl->loadBinary();
|
||||
m_currentlyLoadingMod = node;
|
||||
m_refreshingModCount += 1;
|
||||
m_refreshedModCount += 1;
|
||||
|
||||
auto unzipFunction = [this, node]() {
|
||||
log::debug("Unzip");
|
||||
auto res = node->m_impl->unzipGeodeFile(node->getMetadata());
|
||||
return res;
|
||||
};
|
||||
|
||||
auto loadFunction = [this, node, early]() {
|
||||
if (node->shouldLoad()) {
|
||||
log::debug("Load");
|
||||
auto res = node->m_impl->loadBinary();
|
||||
if (!res) {
|
||||
m_problems.push_back({
|
||||
LoadProblem::Type::LoadFailed,
|
||||
node,
|
||||
res.unwrapErr()
|
||||
});
|
||||
log::error("Failed to load binary: {}", res.unwrapErr());
|
||||
log::popNest();
|
||||
m_refreshingModCount -= 1;
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto const& dep : node->m_impl->m_dependants) {
|
||||
m_modsToLoad.push_front(dep);
|
||||
}
|
||||
}
|
||||
|
||||
m_refreshingModCount -= 1;
|
||||
|
||||
log::popNest();
|
||||
};
|
||||
|
||||
if (early) {
|
||||
auto res = unzipFunction();
|
||||
if (!res) {
|
||||
m_problems.push_back({
|
||||
LoadProblem::Type::LoadFailed,
|
||||
LoadProblem::Type::UnzipFailed,
|
||||
node,
|
||||
res.unwrapErr()
|
||||
});
|
||||
log::error("Failed to load binary: {}", res.unwrapErr());
|
||||
log::error("Failed to unzip: {}", res.unwrapErr());
|
||||
log::popNest();
|
||||
m_refreshingModCount -= 1;
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto const& dep : node->m_impl->m_dependants) {
|
||||
this->loadModGraph(dep, early);
|
||||
}
|
||||
loadFunction();
|
||||
}
|
||||
else {
|
||||
std::thread([=]() {
|
||||
auto res = unzipFunction();
|
||||
queueInMainThread([=]() {
|
||||
if (!res) {
|
||||
m_problems.push_back({
|
||||
LoadProblem::Type::UnzipFailed,
|
||||
node,
|
||||
res.unwrapErr()
|
||||
});
|
||||
log::error("Failed to unzip: {}", res.unwrapErr());
|
||||
log::popNest();
|
||||
m_refreshingModCount -= 1;
|
||||
return;
|
||||
}
|
||||
loadFunction();
|
||||
});
|
||||
}).detach();
|
||||
}
|
||||
|
||||
log::popNest();
|
||||
}
|
||||
|
||||
void Loader::Impl::findProblems() {
|
||||
|
@ -568,12 +618,19 @@ void Loader::Impl::refreshModGraph() {
|
|||
else
|
||||
m_loadingState = LoadingState::Mods;
|
||||
|
||||
queueInMainThread([]() {
|
||||
Loader::get()->m_impl->continueRefreshModGraph();
|
||||
queueInMainThread([&]() {
|
||||
this->continueRefreshModGraph();
|
||||
});
|
||||
}
|
||||
|
||||
void Loader::Impl::continueRefreshModGraph() {
|
||||
if (m_refreshingModCount != 0) {
|
||||
queueInMainThread([&]() {
|
||||
this->continueRefreshModGraph();
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
log::info("Continuing mod graph refresh...");
|
||||
log::pushNest();
|
||||
|
||||
|
@ -585,7 +642,7 @@ void Loader::Impl::continueRefreshModGraph() {
|
|||
log::pushNest();
|
||||
this->loadModGraph(m_modsToLoad.front(), false);
|
||||
log::popNest();
|
||||
m_modsToLoad.pop();
|
||||
m_modsToLoad.pop_front();
|
||||
if (m_modsToLoad.empty())
|
||||
m_loadingState = LoadingState::Problems;
|
||||
break;
|
||||
|
@ -608,8 +665,8 @@ void Loader::Impl::continueRefreshModGraph() {
|
|||
log::info("Took {}s", static_cast<float>(time) / 1000.f);
|
||||
|
||||
if (m_loadingState != LoadingState::Done) {
|
||||
queueInMainThread([]() {
|
||||
Loader::get()->m_impl->continueRefreshModGraph();
|
||||
queueInMainThread([&]() {
|
||||
this->continueRefreshModGraph();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ namespace geode {
|
|||
std::vector<ghc::filesystem::path> m_modSearchDirectories;
|
||||
std::vector<LoadProblem> m_problems;
|
||||
std::unordered_map<std::string, Mod*> m_mods;
|
||||
std::queue<Mod*> m_modsToLoad;
|
||||
std::deque<Mod*> m_modsToLoad;
|
||||
std::vector<ghc::filesystem::path> m_texturePaths;
|
||||
bool m_isSetup = false;
|
||||
|
||||
|
@ -83,6 +83,11 @@ namespace geode {
|
|||
std::mutex m_nextModAccessMutex;
|
||||
Mod* m_nextMod = nullptr;
|
||||
|
||||
Mod* m_currentlyLoadingMod = nullptr;
|
||||
|
||||
int m_refreshingModCount = 0;
|
||||
int m_refreshedModCount = 0;
|
||||
|
||||
void provideNextMod(Mod* mod);
|
||||
Mod* takeNextMod();
|
||||
void releaseNextMod();
|
||||
|
|
|
@ -568,21 +568,25 @@ Result<> Mod::Impl::createTempDir() {
|
|||
return Err("Unable to create mod runtime directory");
|
||||
}
|
||||
|
||||
// Unzip .geode file into temp dir
|
||||
GEODE_UNWRAP_INTO(auto unzip, file::Unzip::create(m_metadata.getPath()));
|
||||
if (!unzip.hasEntry(m_metadata.getBinaryName())) {
|
||||
return Err(
|
||||
fmt::format("Unable to find platform binary under the name \"{}\"", m_metadata.getBinaryName())
|
||||
);
|
||||
}
|
||||
GEODE_UNWRAP(unzip.extractAllTo(tempPath));
|
||||
|
||||
// Mark temp dir creation as succesful
|
||||
m_tempDirName = tempPath;
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
Result<> Mod::Impl::unzipGeodeFile(ModMetadata metadata) {
|
||||
// Unzip .geode file into temp dir
|
||||
GEODE_UNWRAP_INTO(auto unzip, file::Unzip::create(metadata.getPath()));
|
||||
if (!unzip.hasEntry(metadata.getBinaryName())) {
|
||||
return Err(
|
||||
fmt::format("Unable to find platform binary under the name \"{}\"", metadata.getBinaryName())
|
||||
);
|
||||
}
|
||||
GEODE_UNWRAP(unzip.extractAllTo(dirs::getModRuntimeDir() / metadata.getID()));
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
ghc::filesystem::path Mod::Impl::getConfigDir(bool create) const {
|
||||
auto dir = dirs::getModConfigDir() / m_metadata.getID();
|
||||
if (create) {
|
||||
|
|
|
@ -75,6 +75,9 @@ namespace geode {
|
|||
Result<> unloadPlatformBinary();
|
||||
Result<> createTempDir();
|
||||
|
||||
// called on a separate thread
|
||||
Result<> unzipGeodeFile(ModMetadata metadata);
|
||||
|
||||
void setupSettings();
|
||||
|
||||
std::string getID() const;
|
||||
|
|
|
@ -87,6 +87,11 @@ bool ProblemsListCell::init(LoadProblem problem, ProblemsListPopup* list, CCSize
|
|||
icon = "info-alert.png"_spr;
|
||||
message = fmt::format("{} is incompatible with {}", cause, problem.message);
|
||||
break;
|
||||
case LoadProblem::Type::UnzipFailed:
|
||||
icon = "info-alert.png"_spr;
|
||||
message = fmt::format("{} has failed unzipping", cause);
|
||||
m_longMessage = problem.message;
|
||||
break;
|
||||
}
|
||||
|
||||
m_problem = std::move(problem);
|
||||
|
|
Loading…
Reference in a new issue