mirror of
https://github.com/geode-sdk/geode.git
synced 2024-11-14 19:15:05 -05:00
Compare commits
13 commits
0ee9aebdee
...
f96ea5e727
Author | SHA1 | Date | |
---|---|---|---|
|
f96ea5e727 | ||
|
0b2fc66a89 | ||
|
df2528c8a5 | ||
|
03a4387c80 | ||
|
5c85b3c48d | ||
|
123b3abff3 | ||
|
6d13f7837d | ||
|
9b95301472 | ||
|
02845d967e | ||
|
2d66279243 | ||
|
b662aac29d | ||
|
c197e2913c | ||
|
ab196b9adf |
7 changed files with 80 additions and 31 deletions
|
@ -236,8 +236,8 @@ if (ANDROID)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(MAT_JSON_AS_INTERFACE ON)
|
set(MAT_JSON_AS_INTERFACE ON)
|
||||||
CPMAddPackage("gh:geode-sdk/result@1.2.0")
|
CPMAddPackage("gh:geode-sdk/result@1.2.1")
|
||||||
CPMAddPackage("gh:geode-sdk/json@3.0.2")
|
CPMAddPackage("gh:geode-sdk/json@3.0.3")
|
||||||
CPMAddPackage("gh:fmtlib/fmt#11.0.2")
|
CPMAddPackage("gh:fmtlib/fmt#11.0.2")
|
||||||
|
|
||||||
target_compile_definitions(${PROJECT_NAME} INTERFACE MAT_JSON_DYNAMIC=1)
|
target_compile_definitions(${PROJECT_NAME} INTERFACE MAT_JSON_DYNAMIC=1)
|
||||||
|
@ -267,7 +267,7 @@ if (DEFINED GEODE_TULIPHOOK_REPO_PATH)
|
||||||
message(STATUS "Using ${GEODE_TULIPHOOK_REPO_PATH} for TulipHook")
|
message(STATUS "Using ${GEODE_TULIPHOOK_REPO_PATH} for TulipHook")
|
||||||
add_subdirectory(${GEODE_TULIPHOOK_REPO_PATH} ${GEODE_TULIPHOOK_REPO_PATH}/build)
|
add_subdirectory(${GEODE_TULIPHOOK_REPO_PATH} ${GEODE_TULIPHOOK_REPO_PATH}/build)
|
||||||
else()
|
else()
|
||||||
CPMAddPackage("gh:geode-sdk/TulipHook@2.4.0")
|
CPMAddPackage("gh:geode-sdk/TulipHook@2.4.1")
|
||||||
endif()
|
endif()
|
||||||
set(CMAKE_WARN_DEPRECATED ON CACHE BOOL "" FORCE)
|
set(CMAKE_WARN_DEPRECATED ON CACHE BOOL "" FORCE)
|
||||||
|
|
||||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
||||||
4.0.0
|
4.0.0-alpha.1
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
namespace geode {
|
namespace geode {
|
||||||
namespace geode_internal {
|
namespace geode_internal {
|
||||||
template <class T>
|
template <class T, class P>
|
||||||
struct TaskPromise;
|
struct TaskPromise;
|
||||||
|
|
||||||
template <class T, class P>
|
template <class T, class P>
|
||||||
|
@ -161,7 +161,7 @@ namespace geode {
|
||||||
template <std::move_constructible T2, std::move_constructible P2>
|
template <std::move_constructible T2, std::move_constructible P2>
|
||||||
friend class Task;
|
friend class Task;
|
||||||
|
|
||||||
template <class>
|
template <class, class>
|
||||||
friend struct geode_internal::TaskPromise;
|
friend struct geode_internal::TaskPromise;
|
||||||
|
|
||||||
template <class, class>
|
template <class, class>
|
||||||
|
@ -322,7 +322,7 @@ namespace geode {
|
||||||
template <std::move_constructible T2, std::move_constructible P2>
|
template <std::move_constructible T2, std::move_constructible P2>
|
||||||
friend class Task;
|
friend class Task;
|
||||||
|
|
||||||
template <class>
|
template <class, class>
|
||||||
friend struct geode_internal::TaskPromise;
|
friend struct geode_internal::TaskPromise;
|
||||||
|
|
||||||
template <class, class>
|
template <class, class>
|
||||||
|
@ -924,12 +924,22 @@ namespace geode {
|
||||||
//
|
//
|
||||||
// The body of the coroutine is ran in whatever thread it got called in.
|
// The body of the coroutine is ran in whatever thread it got called in.
|
||||||
// TODO: maybe guarantee main thread?
|
// TODO: maybe guarantee main thread?
|
||||||
|
//
|
||||||
|
// The coroutine can also yield progress values using `co_yield`:
|
||||||
|
// ```
|
||||||
|
// Task<std::string, int> someTask() {
|
||||||
|
// for (int i = 0; i < 10; i++) {
|
||||||
|
// co_yield i;
|
||||||
|
// }
|
||||||
|
// co_return "done!";
|
||||||
|
// }
|
||||||
|
// ```
|
||||||
|
|
||||||
namespace geode {
|
namespace geode {
|
||||||
namespace geode_internal {
|
namespace geode_internal {
|
||||||
template <class T>
|
template <class T, class P>
|
||||||
struct TaskPromise {
|
struct TaskPromise {
|
||||||
using MyTask = Task<T>;
|
using MyTask = Task<T, P>;
|
||||||
std::weak_ptr<typename MyTask::Handle> m_handle;
|
std::weak_ptr<typename MyTask::Handle> m_handle;
|
||||||
|
|
||||||
~TaskPromise() {
|
~TaskPromise() {
|
||||||
|
@ -948,10 +958,15 @@ namespace geode {
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
void return_value(T&& x) {
|
void return_value(T x) {
|
||||||
MyTask::finish(m_handle.lock(), std::move(x));
|
MyTask::finish(m_handle.lock(), std::move(x));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::suspend_never yield_value(P value) {
|
||||||
|
MyTask::progress(m_handle.lock(), std::move(value));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
bool isCancelled() {
|
bool isCancelled() {
|
||||||
if (auto p = m_handle.lock()) {
|
if (auto p = m_handle.lock()) {
|
||||||
return p->is(MyTask::Status::Cancelled);
|
return p->is(MyTask::Status::Cancelled);
|
||||||
|
@ -968,8 +983,8 @@ namespace geode {
|
||||||
return task.isFinished();
|
return task.isFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class U>
|
template <class U, class V>
|
||||||
void await_suspend(std::coroutine_handle<TaskPromise<U>> handle) {
|
void await_suspend(std::coroutine_handle<TaskPromise<U, V>> handle) {
|
||||||
if (handle.promise().isCancelled()) {
|
if (handle.promise().isCancelled()) {
|
||||||
handle.destroy();
|
handle.destroy();
|
||||||
return;
|
return;
|
||||||
|
@ -981,7 +996,7 @@ namespace geode {
|
||||||
handle.destroy();
|
handle.destroy();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
parentHandle->m_extraData = std::make_unique<typename Task<U>::Handle::ExtraData>(
|
parentHandle->m_extraData = std::make_unique<typename Task<U, V>::Handle::ExtraData>(
|
||||||
static_cast<void*>(new EventListener<Task<T, P>>(
|
static_cast<void*>(new EventListener<Task<T, P>>(
|
||||||
[handle](auto* event) {
|
[handle](auto* event) {
|
||||||
if (event->getValue()) {
|
if (event->getValue()) {
|
||||||
|
@ -1014,7 +1029,7 @@ auto operator co_await(geode::Task<T, P> task) {
|
||||||
return geode::geode_internal::TaskAwaiter<T, P>{task};
|
return geode::geode_internal::TaskAwaiter<T, P>{task};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class... Args>
|
template <class T, class P, class... Args>
|
||||||
struct std::coroutine_traits<geode::Task<T>, Args...> {
|
struct std::coroutine_traits<geode::Task<T, P>, Args...> {
|
||||||
using promise_type = geode::geode_internal::TaskPromise<T>;
|
using promise_type = geode::geode_internal::TaskPromise<T, P>;
|
||||||
};
|
};
|
|
@ -41,9 +41,9 @@ $execute {
|
||||||
// hook them to call our own handler
|
// hook them to call our own handler
|
||||||
if (LoaderImpl::get()->isForwardCompatMode()) return;
|
if (LoaderImpl::get()->isForwardCompatMode()) return;
|
||||||
|
|
||||||
#if GEODE_COMP_GD_VERSION == 22060
|
#if GEODE_COMP_GD_VERSION == 22074
|
||||||
const uintptr_t offset1 = 0x75d00; // member function in CCEGLView
|
const uintptr_t offset1 = 0x75D90; // member function in CCEGLView
|
||||||
const uintptr_t offset2 = 0x75d60; // static function
|
const uintptr_t offset2 = 0x75DF0; // static function
|
||||||
|
|
||||||
(void) Mod::get()->hook(
|
(void) Mod::get()->hook(
|
||||||
reinterpret_cast<void*>(geode::base::getCocos() + offset1),
|
reinterpret_cast<void*>(geode::base::getCocos() + offset1),
|
||||||
|
|
|
@ -136,7 +136,7 @@ void SettingNodeV3::updateState(CCNode* invoker) {
|
||||||
m_impl->bg->setOpacity(75);
|
m_impl->bg->setOpacity(75);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_impl->nameMenu->setContentWidth(this->getContentWidth() - m_impl->buttonMenu->getContentWidth() - 20);
|
m_impl->nameMenu->setContentWidth(this->getContentWidth() - m_impl->buttonMenu->getContentWidth() - 25);
|
||||||
m_impl->nameMenu->updateLayout();
|
m_impl->nameMenu->updateLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -462,6 +462,7 @@ void FileSettingNodeV3::updateState(CCNode* invoker) {
|
||||||
// which is clever and good UX but also a hack so I also need to hack to support that
|
// which is clever and good UX but also a hack so I also need to hack to support that
|
||||||
const auto isTextualDefaultValue = [this, setting = this->getSetting()]() {
|
const auto isTextualDefaultValue = [this, setting = this->getSetting()]() {
|
||||||
if (this->hasNonDefaultValue()) return false;
|
if (this->hasNonDefaultValue()) return false;
|
||||||
|
if (setting->getDefaultValue().string().size() > 20) return false;
|
||||||
std::error_code ec;
|
std::error_code ec;
|
||||||
return setting->isFolder() ?
|
return setting->isFolder() ?
|
||||||
!std::filesystem::is_directory(setting->getDefaultValue(), ec) :
|
!std::filesystem::is_directory(setting->getDefaultValue(), ec) :
|
||||||
|
|
|
@ -1,15 +1,19 @@
|
||||||
#include "ModItem.hpp"
|
#include "ModItem.hpp"
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <Geode/ui/GeodeUI.hpp>
|
#include <Geode/ui/GeodeUI.hpp>
|
||||||
#include <Geode/utils/ColorProvider.hpp>
|
#include <Geode/utils/ColorProvider.hpp>
|
||||||
#include <Geode/binding/ButtonSprite.hpp>
|
#include <Geode/binding/ButtonSprite.hpp>
|
||||||
#include <Geode/loader/Loader.hpp>
|
#include <Geode/loader/Loader.hpp>
|
||||||
#include <vector>
|
#include "ui/mods/GeodeStyle.hpp"
|
||||||
#include "../GeodeStyle.hpp"
|
#include "ui/mods/popups/ModPopup.hpp"
|
||||||
#include "../popups/ModPopup.hpp"
|
#include "ui/mods/popups/DevPopup.hpp"
|
||||||
#include "../popups/DevPopup.hpp"
|
|
||||||
#include "ui/mods/popups/ModErrorPopup.hpp"
|
#include "ui/mods/popups/ModErrorPopup.hpp"
|
||||||
#include "ui/mods/sources/ModSource.hpp"
|
#include "ui/mods/sources/ModSource.hpp"
|
||||||
#include "../../GeodeUIEvent.hpp"
|
#include "ui/GeodeUIEvent.hpp"
|
||||||
|
|
||||||
bool ModItem::init(ModSource&& source) {
|
bool ModItem::init(ModSource&& source) {
|
||||||
if (!CCNode::init())
|
if (!CCNode::init())
|
||||||
|
@ -422,13 +426,31 @@ void ModItem::updateState() {
|
||||||
// If there were problems, tint the BG red
|
// If there were problems, tint the BG red
|
||||||
m_outdatedLabel->setVisible(false);
|
m_outdatedLabel->setVisible(false);
|
||||||
if (m_source.asMod()) {
|
if (m_source.asMod()) {
|
||||||
|
std::optional<LoadProblem> targetsOutdated = m_source.asMod()->targetsOutdatedVersion();
|
||||||
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()->targetsOutdatedVersion()) {
|
if (!wantsRestart && targetsOutdated) {
|
||||||
|
LoadProblem problem = targetsOutdated.value();
|
||||||
m_bg->setColor("mod-list-outdated-label"_cc3b);
|
m_bg->setColor("mod-list-outdated-label"_cc3b);
|
||||||
m_bg->setOpacity(isGeodeTheme() ? 25 : 90);
|
m_bg->setOpacity(isGeodeTheme() ? 25 : 90);
|
||||||
|
std::string content;
|
||||||
|
if (
|
||||||
|
problem.type == LoadProblem::Type::UnsupportedGeodeVersion ||
|
||||||
|
problem.type == LoadProblem::Type::NeedsNewerGeodeVersion
|
||||||
|
) {
|
||||||
|
content = fmt::format(
|
||||||
|
"Outdated (Geode {})",
|
||||||
|
m_source.getMetadata().getGeodeVersion().toNonVString()
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
content = fmt::format(
|
||||||
|
"Outdated (GD {})",
|
||||||
|
m_source.getMetadata().getGameVersion().value_or("*")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
m_outdatedLabel->setString(content.c_str());
|
||||||
m_outdatedLabel->setVisible(true);
|
m_outdatedLabel->setVisible(true);
|
||||||
m_developers->setVisible(false);
|
m_developers->setVisible(false);
|
||||||
}
|
}
|
||||||
|
@ -568,13 +590,13 @@ void ModItem::onViewError(CCObject*) {
|
||||||
"the mod</c> that supports the newer version.";
|
"the mod</c> that supports the newer version.";
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case LoadProblem::Type::UnsupportedGeodeVersion: {
|
case LoadProblem::Type::NeedsNewerGeodeVersion: {
|
||||||
issue = "This mod is made for a <cp>newer version of Geode</c>.";
|
issue = "This mod is made for a <cp>newer version of Geode</c>.";
|
||||||
howToFix = "<cp>update Geode</c> by enabling <co>Automatic Updates</c> "
|
howToFix = "<cp>update Geode</c> by enabling <co>Automatic Updates</c> "
|
||||||
"or redownloading it from the Geode website.";
|
"or redownloading it from the Geode website.";
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case LoadProblem::Type::NeedsNewerGeodeVersion: {
|
case LoadProblem::Type::UnsupportedGeodeVersion: {
|
||||||
issue = "This mod is made for an <cy>older version of Geode</c>.";
|
issue = "This mod is made for an <cy>older version of Geode</c>.";
|
||||||
howToFix = "wait for the developer to <cj>release an update to "
|
howToFix = "wait for the developer to <cj>release an update to "
|
||||||
"the mod</c> that supports the newer version.";
|
"the mod</c> that supports the newer version.";
|
||||||
|
|
|
@ -352,7 +352,7 @@ bool ModList::init(ModListSource* src, CCSize const& size) {
|
||||||
m_statusDetailsBtn->setID("status-details-button");
|
m_statusDetailsBtn->setID("status-details-button");
|
||||||
m_statusContainer->addChild(m_statusDetailsBtn);
|
m_statusContainer->addChild(m_statusDetailsBtn);
|
||||||
|
|
||||||
m_statusDetails = SimpleTextArea::create("", "chatFont.fnt", .6f);
|
m_statusDetails = SimpleTextArea::create("", "chatFont.fnt", .6f, 650.f);
|
||||||
m_statusDetails->setID("status-details-input");
|
m_statusDetails->setID("status-details-input");
|
||||||
m_statusDetails->setAlignment(kCCTextAlignmentCenter);
|
m_statusDetails->setAlignment(kCCTextAlignmentCenter);
|
||||||
m_statusContainer->addChild(m_statusDetails);
|
m_statusContainer->addChild(m_statusDetails);
|
||||||
|
@ -649,8 +649,19 @@ void ModList::showStatus(ModListStatus status, std::string const& message, std::
|
||||||
m_statusContainer->setVisible(true);
|
m_statusContainer->setVisible(true);
|
||||||
m_statusDetails->setVisible(false);
|
m_statusDetails->setVisible(false);
|
||||||
m_statusDetailsBtn->setVisible(details.has_value());
|
m_statusDetailsBtn->setVisible(details.has_value());
|
||||||
m_statusLoadingCircle->setVisible(std::holds_alternative<ModListUnkProgressStatus>(status));
|
m_statusLoadingCircle->setVisible(
|
||||||
m_statusLoadingBar->setVisible(std::holds_alternative<ModListProgressStatus>(status));
|
std::holds_alternative<ModListUnkProgressStatus>(status)
|
||||||
|
|| std::holds_alternative<ModListProgressStatus>(status)
|
||||||
|
);
|
||||||
|
|
||||||
|
// the loading bar makes no sense to display - it's meant for progress of mod list page loading
|
||||||
|
// however the mod list pages are so small, that there usually isn't a scenario where the loading
|
||||||
|
// takes longer than a single frame - therefore this is useless
|
||||||
|
// server processing time isn't included in this - it's only after the server starts responding
|
||||||
|
// that we get any progress information
|
||||||
|
// also the position is wrong if you wanna restore the functionality
|
||||||
|
//m_statusLoadingBar->setVisible(std::holds_alternative<ModListProgressStatus>(status));
|
||||||
|
m_statusLoadingBar->setVisible(false);
|
||||||
|
|
||||||
// Update progress bar
|
// Update progress bar
|
||||||
if (auto per = std::get_if<ModListProgressStatus>(&status)) {
|
if (auto per = std::get_if<ModListProgressStatus>(&status)) {
|
||||||
|
|
Loading…
Reference in a new issue