mirror of
https://github.com/geode-sdk/geode.git
synced 2025-04-15 14:34:50 -04:00
Merge branch 'geode-sdk:main' into main
This commit is contained in:
commit
1e8500c5db
11 changed files with 218 additions and 33 deletions
4
.git-blame-ignore-revs
Normal file
4
.git-blame-ignore-revs
Normal file
|
@ -0,0 +1,4 @@
|
|||
# add clang format (#62)
|
||||
11e81e3d64313d319955d9a214ad0ded78985bed
|
||||
2bb416ba77f2f01897cc10a1afac40c957feadfc
|
||||
|
|
@ -236,7 +236,7 @@ if (ANDROID)
|
|||
endif()
|
||||
|
||||
set(MAT_JSON_AS_INTERFACE ON)
|
||||
CPMAddPackage("gh:geode-sdk/result@1.3.2")
|
||||
CPMAddPackage("gh:geode-sdk/result@1.3.3")
|
||||
CPMAddPackage("gh:geode-sdk/json@3.2.1")
|
||||
CPMAddPackage("gh:fmtlib/fmt#11.0.2")
|
||||
|
||||
|
|
27
flash.toml
27
flash.toml
|
@ -4,7 +4,7 @@
|
|||
|
||||
[project]
|
||||
name = "Geode"
|
||||
version = "v3.0.0"
|
||||
version = "" # dont bother
|
||||
repository = "https://github.com/geode-sdk/geode"
|
||||
tree = "https://github.com/geode-sdk/geode/tree/main"
|
||||
icon = "loader/resources/logos/geode-circle.png"
|
||||
|
@ -18,6 +18,14 @@ assets = [
|
|||
"docs/assets/handbook/vol2/*.png",
|
||||
]
|
||||
|
||||
[[external-libs]]
|
||||
pattern = "matjson"
|
||||
repository = "https://github.com/geode-sdk/json"
|
||||
|
||||
[[external-libs]]
|
||||
pattern = "Result.hpp"
|
||||
repository = "https://github.com/geode-sdk/result"
|
||||
|
||||
[[sources]]
|
||||
name = "Geode"
|
||||
dir = "loader/include"
|
||||
|
@ -42,6 +50,23 @@ include = [
|
|||
# Bindings are generated at compile time
|
||||
exists-online = false
|
||||
|
||||
[ignore]
|
||||
patterns-name = [
|
||||
# anything that starts with a double underscore
|
||||
# shouldnt be included
|
||||
"^__",
|
||||
"^tinyxml2$",
|
||||
"^format_as$",
|
||||
# operator overloads
|
||||
"^operator\\W"
|
||||
]
|
||||
patterns-full = [
|
||||
"^geode::modifier",
|
||||
"^geode::prelude",
|
||||
"^geode::stl",
|
||||
"^geode::geode_internal"
|
||||
]
|
||||
|
||||
# CMake options
|
||||
|
||||
[cmake]
|
||||
|
|
|
@ -693,7 +693,7 @@ namespace pugi
|
|||
xml_node& operator*() const;
|
||||
xml_node* operator->() const;
|
||||
|
||||
const xml_node_iterator& operator++();
|
||||
xml_node_iterator& operator++();
|
||||
xml_node_iterator operator++(int);
|
||||
|
||||
const xml_node_iterator& operator--();
|
||||
|
@ -735,7 +735,7 @@ namespace pugi
|
|||
xml_attribute& operator*() const;
|
||||
xml_attribute* operator->() const;
|
||||
|
||||
const xml_attribute_iterator& operator++();
|
||||
xml_attribute_iterator& operator++();
|
||||
xml_attribute_iterator operator++(int);
|
||||
|
||||
const xml_attribute_iterator& operator--();
|
||||
|
@ -769,7 +769,7 @@ namespace pugi
|
|||
xml_node& operator*() const;
|
||||
xml_node* operator->() const;
|
||||
|
||||
const xml_named_node_iterator& operator++();
|
||||
xml_named_node_iterator& operator++();
|
||||
xml_named_node_iterator operator++(int);
|
||||
|
||||
private:
|
||||
|
|
|
@ -17,6 +17,9 @@ namespace geode {
|
|||
struct TaskAwaiter;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
concept is_task_type = std::move_constructible<T> || std::same_as<T, void>;
|
||||
|
||||
/**
|
||||
* Tasks represent an asynchronous operation that will be finished at some
|
||||
* unknown point in the future. Tasks can report their progress, and will
|
||||
|
@ -40,17 +43,17 @@ namespace geode {
|
|||
* Once a Task has finished or has been cancelled, it can no longer be
|
||||
* revived
|
||||
* @tparam T The type the Task will eventually finish to. This type must be
|
||||
* move-constructible; though as there is no way to move the value out
|
||||
* move-constructible or void; though as there is no way to move the value out
|
||||
* of the Task (because of potentially multiple listeners), one
|
||||
* should ensure they can reasonably copy the value out in some form if they
|
||||
* wish to gain ownership of it after the Task is finished
|
||||
* @tparam P The type of the progress values the Task (may) post
|
||||
*/
|
||||
template <typename T, std::move_constructible P = std::monostate>
|
||||
requires std::move_constructible<T> || std::same_as<T, void>
|
||||
template <is_task_type T, std::move_constructible P = std::monostate>
|
||||
class [[nodiscard]] Task final {
|
||||
using Type = std::conditional_t<std::same_as<T, void>, TaskVoid, T>;
|
||||
public:
|
||||
using Type = std::conditional_t<std::same_as<T, void>, TaskVoid, T>;
|
||||
|
||||
/**
|
||||
* A struct used for cancelling Tasks; Tasks may return an instance of
|
||||
* this struct to cancel themselves, or to mark they have handled
|
||||
|
@ -78,8 +81,7 @@ namespace geode {
|
|||
return m_value.index() == 1;
|
||||
}
|
||||
|
||||
template <typename T2, std::move_constructible P2>
|
||||
requires std::move_constructible<T2> || std::same_as<T2, void>
|
||||
template <is_task_type T2, std::move_constructible P2>
|
||||
friend class Task;
|
||||
|
||||
public:
|
||||
|
@ -170,8 +172,7 @@ namespace geode {
|
|||
return m_status == status;
|
||||
}
|
||||
|
||||
template <typename T2, std::move_constructible P2>
|
||||
requires std::move_constructible<T2> || std::same_as<T2, void>
|
||||
template <is_task_type T2, std::move_constructible P2>
|
||||
friend class Task;
|
||||
|
||||
template <class, class>
|
||||
|
@ -227,8 +228,7 @@ namespace geode {
|
|||
return Event(handle, std::variant<Type*, P*, Cancel>(std::in_place_index<2>, Cancel()));
|
||||
}
|
||||
|
||||
template <typename T2, std::move_constructible P2>
|
||||
requires std::move_constructible<T2> || std::same_as<T2, void>
|
||||
template <is_task_type T2, std::move_constructible P2>
|
||||
friend class Task;
|
||||
|
||||
public:
|
||||
|
@ -333,8 +333,7 @@ namespace geode {
|
|||
}
|
||||
}
|
||||
|
||||
template <typename T2, std::move_constructible P2>
|
||||
requires std::move_constructible<T2> || std::same_as<T2, void>
|
||||
template <is_task_type T2, std::move_constructible P2>
|
||||
friend class Task;
|
||||
|
||||
template <class, class>
|
||||
|
@ -1094,7 +1093,7 @@ namespace geode {
|
|||
);
|
||||
}
|
||||
|
||||
T await_resume() {
|
||||
Task<T, P>::Type await_resume() {
|
||||
return std::move(*task.getFinishedValue());
|
||||
}
|
||||
};
|
||||
|
|
100
loader/include/Geode/utils/async.hpp
Normal file
100
loader/include/Geode/utils/async.hpp
Normal file
|
@ -0,0 +1,100 @@
|
|||
#pragma once
|
||||
|
||||
#include <coroutine>
|
||||
#include <Geode/DefaultInclude.hpp>
|
||||
#include "Task.hpp"
|
||||
|
||||
namespace geode {
|
||||
template <is_task_type T = void, typename P = std::monostate>
|
||||
class CoTask final {
|
||||
using Type = Task<T, P>::Type;
|
||||
Task<T, P> m_task;
|
||||
public:
|
||||
using promise_type = std::coroutine_traits<Task<T, P>>::promise_type;
|
||||
auto operator<=>(const CoTask&) const = default;
|
||||
operator Task<T, P>() { return std::move(m_task); }
|
||||
|
||||
CoTask() = default;
|
||||
CoTask(CoTask&&) = default;
|
||||
CoTask(Task<T, P>&& task) : m_task(std::move(task)) {}
|
||||
|
||||
|
||||
Type* getFinishedValue() { return m_task.getFinishedValue(); }
|
||||
void cancel() { return m_task.cancel(); }
|
||||
void shallowCancel() { m_task.shallowCancel(); }
|
||||
bool isPending() const { return m_task.isPending(); }
|
||||
bool isFinished() const { return m_task.isFinished(); }
|
||||
bool isCancelled() const { return m_task.isCancelled(); }
|
||||
bool isNull() const { return m_task.isNull(); }
|
||||
|
||||
Task<T, P> task() { return std::move(m_task); }
|
||||
|
||||
static inline struct {
|
||||
template <typename F>
|
||||
decltype(auto) operator<<(F fn) { return fn(); }
|
||||
} invoke;
|
||||
};
|
||||
|
||||
namespace geode_internal {
|
||||
template <typename T, typename E>
|
||||
struct promise_type {
|
||||
using Inner = std::optional<Result<T, E>>;
|
||||
|
||||
struct: public std::shared_ptr<Inner> {
|
||||
using std::shared_ptr<Inner>::shared_ptr;
|
||||
operator Result<T>() {
|
||||
return (*this->get()).value();
|
||||
}
|
||||
} result{new Inner()};
|
||||
|
||||
std::suspend_never initial_suspend() { return {}; }
|
||||
std::suspend_never final_suspend() noexcept { return {}; }
|
||||
auto get_return_object() { return result; }
|
||||
void unhandled_exception() {}
|
||||
void return_value(Result<T, E>&& value) { *result = std::move(value); }
|
||||
};
|
||||
|
||||
template <typename T, typename E>
|
||||
struct Awaiter {
|
||||
Result<T, E> result;
|
||||
|
||||
bool await_ready() { return result.isOk(); }
|
||||
T&& await_resume() { return std::move(result.unwrap()); }
|
||||
Awaiter(Result<T, E>&& res) : result(std::move(res)) {}
|
||||
|
||||
template <typename U>
|
||||
void await_suspend(std::coroutine_handle<U> handle) {
|
||||
handle.promise().return_value(Err(result.unwrapErr()));
|
||||
handle.destroy();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename E>
|
||||
struct Awaiter<void, E> {
|
||||
Result<void, E> result;
|
||||
|
||||
bool await_ready() { return result.isOk(); }
|
||||
void await_resume() { return; }
|
||||
Awaiter(Result<void, E> res) : result(res) {}
|
||||
|
||||
template <typename U>
|
||||
void await_suspend(std::coroutine_handle<U> handle) {
|
||||
handle.promise().return_value(Err(result.unwrapErr()));
|
||||
handle.destroy();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#define $async(...) geode::CoTask<>::invoke << [__VA_ARGS__]() -> geode::CoTask<>
|
||||
#define $try geode::CoTask<>::invoke << [&]() -> geode::Result
|
||||
};
|
||||
|
||||
template <typename T = void, typename E = std::string>
|
||||
auto operator co_await(geode::Result<T, E>&& res) {
|
||||
return geode::geode_internal::Awaiter { std::move(res) };
|
||||
}
|
||||
|
||||
template <typename T, typename E, typename ...Args>
|
||||
struct std::coroutine_traits<geode::Result<T, E>, Args...> {
|
||||
using promise_type = geode::geode_internal::promise_type<T, E>;
|
||||
};
|
|
@ -209,7 +209,7 @@ namespace geode::utils::ranges {
|
|||
template <ValidContainer C, ValidCUnaryPredicate<C> Predicate>
|
||||
C filter(C const& container, Predicate filterFun) {
|
||||
auto res = C();
|
||||
std::copy_if(container.begin(), container.end(), res.end(), filterFun);
|
||||
std::copy_if(container.begin(), container.end(), std::back_inserter(res), filterFun);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -238,7 +238,7 @@ namespace geode::utils::ranges {
|
|||
typename C::value_type min(C const& container) {
|
||||
auto it = std::min_element(container.begin(), container.end());
|
||||
if (it == container.end()) {
|
||||
return C::value_type();
|
||||
return typename C::value_type();
|
||||
}
|
||||
return *it;
|
||||
}
|
||||
|
@ -264,7 +264,7 @@ namespace geode::utils::ranges {
|
|||
typename C::value_type max(C const& container) {
|
||||
auto it = std::max_element(container.begin(), container.end());
|
||||
if (it == container.end()) {
|
||||
return C::value_type();
|
||||
return typename C::value_type();
|
||||
}
|
||||
return *it;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
#include <Geode/Geode.hpp>
|
||||
|
||||
// TODO: this affects every platform :P, but i cant be bothered rn
|
||||
#ifdef GEODE_IS_WINDOWS
|
||||
|
||||
#include <loader/LoaderImpl.hpp>
|
||||
|
||||
using namespace geode::prelude;
|
||||
|
@ -15,6 +11,7 @@ $execute {
|
|||
// for some reason cocos only properly returns false on winRT, everywhere
|
||||
// else it just closes the whole game
|
||||
|
||||
#if defined(GEODE_IS_WINDOWS)
|
||||
auto addr = reinterpret_cast<uintptr_t>(
|
||||
GetProcAddress(
|
||||
GetModuleHandle("libcocos2d.dll"), "?compileShader@CCGLProgram@cocos2d@@AEAA_NPEAIIPEBD@Z"
|
||||
|
@ -25,9 +22,36 @@ $execute {
|
|||
0x31, 0xc0, // xor eax, eax
|
||||
0xeb, 0x07 // jmp +7 (to a nearby ret)
|
||||
});
|
||||
#elif defined(GEODE_IS_ANDROID64)
|
||||
auto addr = reinterpret_cast<uintptr_t>(
|
||||
dlsym(RTLD_DEFAULT, "_ZN7cocos2d11CCGLProgram13compileShaderEPjjPKc")
|
||||
) + 0x74;
|
||||
|
||||
(void) Mod::get()->patch(reinterpret_cast<void*>(addr), {
|
||||
0x1f, 0x20, 0x03, 0xd5 // nop (skip if statement)
|
||||
});
|
||||
#elif defined(GEODE_IS_ANDROID32)
|
||||
auto addr = reinterpret_cast<uintptr_t>(
|
||||
dlsym(RTLD_DEFAULT, "_ZN7cocos2d11CCGLProgram13compileShaderEPjjPKc")
|
||||
) + 0x43;
|
||||
|
||||
(void) Mod::get()->patch(reinterpret_cast<void*>(addr), {
|
||||
0x14, 0xe0 // b +2c (skip if statement)
|
||||
});
|
||||
#elif defined(GEODE_IS_ARM_MAC)
|
||||
auto addr = base::get() + 0x393aa0;
|
||||
|
||||
(void) Mod::get()->patch(reinterpret_cast<void*>(addr), {
|
||||
0x1f, 0x20, 0x03, 0xd5 // nop (skip if statement)
|
||||
});
|
||||
#elif defined(GEODE_IS_INTEL_MAC)
|
||||
auto addr = base::get() + 0x417f65;
|
||||
|
||||
(void) Mod::get()->patch(reinterpret_cast<void*>(addr), {
|
||||
0x48, 0x90, // nop (skip if statement)
|
||||
});
|
||||
#endif
|
||||
#else
|
||||
#pragma message("Unsupported GD version!")
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -92,6 +92,10 @@ std::string cocos2d::format_as(cocos2d::ccColor4B const& col) {
|
|||
return fmt::format("rgba({}, {}, {}, {})", col.r, col.g, col.b, col.a);
|
||||
}
|
||||
|
||||
std::string cocos2d::format_as(cocos2d::ccColor4F const& col) {
|
||||
return fmt::format("rgba({}, {}, {}, {})", col.r, col.g, col.b, col.a);
|
||||
}
|
||||
|
||||
// Log
|
||||
|
||||
inline static thread_local int32_t s_nestLevel = 0;
|
||||
|
|
|
@ -651,12 +651,6 @@ bool ModPopup::setup(ModSource&& src) {
|
|||
return ListenerResult::Propagate;
|
||||
});
|
||||
|
||||
#ifdef GEODE_IS_WINDOWS
|
||||
if (src.asMod() && src.asMod()->isInternal()) {
|
||||
class S:public CCLayer{CCSize m_size=CCSize(1,1);Ref<CCTexture2D> m_tex=nullptr;Ref<CCGLProgram> m_shader=nullptr;public: bool init()override {if(!CCLayer::init())return false;m_shader=new CCGLProgram();if(!m_shader->initWithVertexShaderByteArray("attribute vec4 a_position;attribute vec2 a_texCoord;varying vec2 v_texCoord;void main(){gl_Position=CC_MVPMatrix*a_position;v_texCoord=a_texCoord;}","varying vec2 v_texCoord;uniform sampler2D CC_Texture0;void main(){vec2 uv=v_texCoord;float t=CC_Time.y;float off=sin(uv.y*4.0-t*2.0)*sin(uv.y*13.-t*4.);float r=texture(CC_Texture0,uv-vec2(off*0.01,0)).r;float g=texture(CC_Texture0,uv-vec2(off*0.03,0)).g;float b=texture(CC_Texture0,uv-vec2(off*0.05,0)).b;vec4 col=vec4(r,g,b,1);col*=vec4(.5,1,.5,1);col=vec4(pow(col.rgb,vec3(.8)),1);gl_FragColor=col;}")){delete m_shader;return false;}uint32_t x=0;m_tex=new CCTexture2D;m_tex->autorelease();m_tex->initWithData(&x,kCCTexture2DPixelFormat_RGBA8888,1,1,CCSize(1,1));m_shader->addAttribute(kCCAttributeNamePosition,kCCVertexAttrib_Position);m_shader->addAttribute(kCCAttributeNameTexCoord,kCCVertexAttrib_TexCoords);m_shader->autorelease();m_shader->link();m_shader->updateUniforms();m_tex->setShaderProgram(m_shader);return true;}void draw()override {CCLayer::draw();glBindTexture(GL_TEXTURE_2D,m_tex->getName());auto size=CCEGLView::get()->getFrameSize();auto winSize=CCDirector::get()->getWinSize();if(size != m_size){m_size=size;glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,size.width,size.height,0,GL_RGBA,GL_UNSIGNED_BYTE,nullptr);}glCopyTexSubImage2D(GL_TEXTURE_2D,0,0,0,0,0,size.width,size.height);m_shader->use();m_tex->drawInRect(CCRect(0.f,winSize.height,winSize.width,-winSize.height));if(auto z=CCScene::get()->getHighestChildZ(); z > this->getZOrder()){this->setZOrder(CCScene::get()->getHighestChildZ()+ 1);}}void add(CCObject*){if(auto* s=S::create())CCScene::get()->addChild(s);}CREATE_FUNC(S);};if(Loader::get()->getVersion()!=VersionInfo(4,2,0))return true;auto* node=m_stats->getChildByIDRecursive("version")->getChildByIDRecursive("value-label");node->setVisible(false);auto pos=node->convertToWorldSpace(node->getContentSize()/ 2.f);auto size=pos - node->convertToWorldSpace(-node->getContentSize()/ 2.f);auto* label=CCLabelBMFont::create("v4.2.0","bigFont.fnt");label->limitLabelWidth(size.x,1.f,0.001f);auto menu=CCMenu::create();auto btn=CCMenuItemSpriteExtra::create(label,this,menu_selector(S::add));btn->setPosition(pos);menu->setPosition(ccp(0,0));menu->addChild(btn);this->addChild(menu);
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
#include <Geode/Loader.hpp>
|
||||
#include <Geode/loader/ModEvent.hpp>
|
||||
#include <Geode/utils/cocos.hpp>
|
||||
#include <chrono>
|
||||
#include "../dependency/main.hpp"
|
||||
#include "Geode/utils/general.hpp"
|
||||
|
||||
using namespace geode::prelude;
|
||||
|
||||
|
@ -25,6 +27,39 @@ $execute {
|
|||
});
|
||||
}
|
||||
|
||||
// Coroutines
|
||||
#include <Geode/utils/async.hpp>
|
||||
auto advanceFrame() {
|
||||
auto [task, finish, progress, cancelled] = Task<void>::spawn();
|
||||
queueInMainThread(std::bind(finish, true));
|
||||
|
||||
return task;
|
||||
}
|
||||
|
||||
$execute {
|
||||
$async() {
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
log::info("Waiting for 10 frames...");
|
||||
for (int i = 0; i < 10; ++i)
|
||||
co_await advanceFrame();
|
||||
|
||||
log::info("Finished waiting! Took {} seconds", std::chrono::duration_cast<std::chrono::seconds>(
|
||||
std::chrono::steady_clock::now() - start
|
||||
).count());
|
||||
};
|
||||
|
||||
auto output = $try<VersionInfo> {
|
||||
log::info("Parsing number 123: {}", co_await utils::numFromString<int>("123"));
|
||||
log::info("Parsing number 12.3: {}", co_await utils::numFromString<int>("12.3"));
|
||||
|
||||
co_return VersionInfo::parse("1.2.3-alpha.4");
|
||||
};
|
||||
|
||||
if (!output) {
|
||||
log::info("$try successfully caught error");
|
||||
}
|
||||
}
|
||||
|
||||
#include <Geode/modify/MenuLayer.hpp>
|
||||
struct $modify(MenuLayer) {
|
||||
bool init() {
|
||||
|
|
Loading…
Add table
Reference in a new issue