Merge branch 'main' of https://github.com/geode-sdk/geode into main

This commit is contained in:
camila314 2022-12-07 13:39:09 -06:00
commit 282797b0ea
32 changed files with 6866 additions and 671 deletions

View file

@ -3,6 +3,7 @@ IndentWidth: 4
AlignAfterOpenBracket: BlockIndent AlignAfterOpenBracket: BlockIndent
AlignEscapedNewlines: Left AlignEscapedNewlines: Left
AlignConsecutiveAssignments: false
AlignOperands: DontAlign AlignOperands: DontAlign
AlignTrailingComments: false AlignTrailingComments: false
@ -22,7 +23,7 @@ AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: Yes AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: true BinPackArguments: false
BinPackParameters: true BinPackParameters: true
BraceWrapping: BraceWrapping:
@ -49,7 +50,7 @@ BraceWrapping:
BreakBeforeBinaryOperators: None BreakBeforeBinaryOperators: None
BreakBeforeBraces: Custom BreakBeforeBraces: Custom
BreakBeforeConceptDeclarations: true BreakBeforeConceptDeclarations: true
BreakBeforeTernaryOperators: true BreakBeforeTernaryOperators: false
BreakConstructorInitializers: AfterColon BreakConstructorInitializers: AfterColon
BreakInheritanceList: AfterColon BreakInheritanceList: AfterColon
BreakStringLiterals: true BreakStringLiterals: true
@ -57,7 +58,7 @@ ColumnLimit: 100
CompactNamespaces: false CompactNamespaces: false
ConstructorInitializerIndentWidth: 4 ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4 ContinuationIndentWidth: 4
Cpp11BracedListStyle: false Cpp11BracedListStyle: true
DeriveLineEnding: false DeriveLineEnding: false
UseCRLF: false UseCRLF: false
@ -84,7 +85,7 @@ IndentCaseLabels: true
IndentExternBlock: Indent IndentExternBlock: Indent
IndentGotoLabels: true IndentGotoLabels: true
IndentPPDirectives: BeforeHash IndentPPDirectives: BeforeHash
IndentRequiresClause: false IndentRequiresClause: true
IndentWrappedFunctionNames: false IndentWrappedFunctionNames: false
# InsertBraces: true # InsertBraces: true
InsertTrailingCommas: None InsertTrailingCommas: None
@ -101,8 +102,9 @@ PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300 PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120 PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000 PenaltyBreakString: 1000
PenaltyBreakOpenParenthesis: 0
PenaltyBreakTemplateDeclaration: 10 PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000 PenaltyExcessCharacter: 10
PenaltyReturnTypeOnItsOwnLine: 1000000 PenaltyReturnTypeOnItsOwnLine: 1000000
PenaltyIndentedWhitespace: 0 PenaltyIndentedWhitespace: 0
@ -121,7 +123,7 @@ SpaceAfterTemplateKeyword: true
SpaceAroundPointerQualifiers: Default SpaceAroundPointerQualifiers: Default
SpaceBeforeAssignmentOperators: true SpaceBeforeAssignmentOperators: true
SpaceBeforeCaseColon: false SpaceBeforeCaseColon: false
SpaceBeforeCpp11BracedList: true SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements SpaceBeforeParens: ControlStatements

View file

@ -210,6 +210,7 @@ class cocos2d::CCFileUtils : cocos2d::TypeInfo {
virtual void addSearchPath(const char* path); virtual void addSearchPath(const char* path);
virtual void removeSearchPath(const char *path); virtual void removeSearchPath(const char *path);
virtual std::string fullPathForFilename(const char* filename, bool unk); virtual std::string fullPathForFilename(const char* filename, bool unk);
void removeAllPaths() = mac 0x241600;
} }
class cocos2d::CCGLProgram { class cocos2d::CCGLProgram {

View file

@ -71,8 +71,7 @@ namespace cocos2d::extension {}
#define GEODE_FILL_CONSTRUCTOR(Class_, Offset_) \ #define GEODE_FILL_CONSTRUCTOR(Class_, Offset_) \
Class_(std::monostate, size_t fill) : \ Class_(std::monostate, size_t fill) : \
Class_({}, std::memset(reinterpret_cast<std::byte*>(this) + Offset_, 0, fill - Offset_)) { \ Class_({}, std::memset(reinterpret_cast<std::byte*>(this) + Offset_, 0, fill - Offset_)) {} \
} \
Class_(std::monostate, void*) Class_(std::monostate, void*)
#define GEODE_MONOSTATE_CONSTRUCTOR_BEGIN(Class_) \ #define GEODE_MONOSTATE_CONSTRUCTOR_BEGIN(Class_) \
@ -97,10 +96,71 @@ namespace cocos2d::extension {}
GEODE_EXPAND(GEODE_NUMBER_OF_ARGS_(__VA_ARGS__, GEODE_NUMBER_SEQUENCE(), )) GEODE_EXPAND(GEODE_NUMBER_OF_ARGS_(__VA_ARGS__, GEODE_NUMBER_SEQUENCE(), ))
#define GEODE_NUMBER_OF_ARGS_(...) GEODE_EXPAND(GEODE_NUMBER_OF_ARGS_N(__VA_ARGS__)) #define GEODE_NUMBER_OF_ARGS_(...) GEODE_EXPAND(GEODE_NUMBER_OF_ARGS_N(__VA_ARGS__))
#define GEODE_NUMBER_OF_ARGS_N( \ #define GEODE_NUMBER_OF_ARGS_N( \
_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \ _1, \
_21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, \ _2, \
_40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, \ _3, \
_59, _60, _61, _62, _63, N, ... \ _4, \
_5, \
_6, \
_7, \
_8, \
_9, \
_10, \
_11, \
_12, \
_13, \
_14, \
_15, \
_16, \
_17, \
_18, \
_19, \
_20, \
_21, \
_22, \
_23, \
_24, \
_25, \
_26, \
_27, \
_28, \
_29, \
_30, \
_31, \
_32, \
_33, \
_34, \
_35, \
_36, \
_37, \
_38, \
_39, \
_40, \
_41, \
_42, \
_43, \
_44, \
_45, \
_46, \
_47, \
_48, \
_49, \
_50, \
_51, \
_52, \
_53, \
_54, \
_55, \
_56, \
_57, \
_58, \
_59, \
_60, \
_61, \
_62, \
_63, \
N, \
... \
) \ ) \
N N
#define GEODE_NUMBER_SEQUENCE() \ #define GEODE_NUMBER_SEQUENCE() \
@ -108,6 +168,21 @@ namespace cocos2d::extension {}
40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, \ 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, \
18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
#define $execute \
template <class> \
void GEODE_CONCAT(geodeExecFunction, __LINE__)(); \
namespace { \
struct GEODE_CONCAT(ExecFuncUnique, __LINE__) {}; \
} \
static inline auto GEODE_CONCAT(Exec, __LINE__) = \
(Loader::get()->scheduleOnModLoad( \
getMod(), \
&GEODE_CONCAT(geodeExecFunction, __LINE__) < GEODE_CONCAT(ExecFuncUnique, __LINE__) > \
), \
0); \
template <class> \
void GEODE_CONCAT(geodeExecFunction, __LINE__)()
// #define GEODE_NEST1(macro, begin) \ // #define GEODE_NEST1(macro, begin) \
// macro(GEODE_CONCAT(begin, 0)), \ // macro(GEODE_CONCAT(begin, 0)), \
// macro(GEODE_CONCAT(begin, 1)), \ // macro(GEODE_CONCAT(begin, 1)), \

View file

@ -0,0 +1,153 @@
#pragma once
#include <cstdint>
#include <array>
namespace geode::stl {
template <class Type>
class AllocatorTemplate {
protected:
inline Type* allocate(size_t count);
inline void deallocate(Type* pointer);
};
#if defined(GEODE_IS_WINDOWS)
template <class Type>
class AllocatorBase {
protected:
inline Type* allocate(size_t count) {
}
inline void deallocate(Type* pointer) {
}
};
#elif defined(GEODE_IS_MACOS) || defined(GEODE_IS_ANDROID)
#elif defined(GEODE_IS_IOS)
#endif
class StringTemplate : public AllocatorBase {
protected:
// depends on already set size and capacity
inline void setStorage(char* pointer) = delete;
inline char* getStorage() = delete;
inline void setSize(size_t size) = delete;
inline size_t getSize() = delete;
inline void setCapacity(size_t capacity) = delete;
inline size_t getCapacity() = delete;
};
#if defined(GEODE_IS_WINDOWS)
class StringBase : public StringTemplate {
protected:
union {
std::array<char, 16> m_smallStorage;
char* m_bigStorage;
};
size_t m_size;
size_t m_capacity;
inline void setStorage(char* storage) {
if (m_capacity > 15) {
return m_bigStorage = storage;
}
}
inline char* getStorage() {
if (m_capacity > 15) {
return m_bigStorage;
}
return m_smallStorage.data();
}
inline void setSize(size_t size) {
m_size = size;
}
inline size_t getSize() {
return m_size;
}
inline void setCapacity(size_t capacity) {
m_capacity = capacity;
}
inline size_t getCapacity() {
return m_capacity;
}
};
#elif defined(GEODE_IS_MACOS) || defined(GEODE_IS_ANDROID)
class StringBase : public StringTemplate {
protected:
char* m_storage;
size_t m_size;
size_t m_capacity;
inline void setStorage(char* storage) {
m_storage = storage;
}
inline char* getStorage() {
return m_storage;
}
inline void setSize(size_t size) {
m_size = size;
}
inline size_t getSize() {
return m_size;
}
inline void setCapacity(size_t capacity) {
m_capacity = capacity;
}
inline size_t getCapacity() {
return m_capacity;
}
};
#elif defined(GEODE_IS_IOS)
class StringBase : public StringTemplate {
protected:
struct Short {
uint8_t sizex2;
std::array<char, 23> shortStorage;
};
struct Long {
size_t capacitym1;
size_t size;
char* longStorage;
};
union {
Short m_short;
Long m_long;
};
inline void setStorage(char* storage) {
m_storage = storage;
}
inline char* getStorage() {
return m_storage;
}
inline void setSize(size_t size) {
m_size = size;
}
inline size_t getSize() {
return m_size;
}
inline void setCapacity(size_t capacity) {
m_capacity = capacity;
}
inline size_t getCapacity() {
return m_capacity;
}
};
#endif
}

View file

@ -296,84 +296,166 @@ namespace gd {
} }
}; };
// template <class Type>
// using vector = std::vector<Type>;
template <typename T> template <typename T>
class GEODE_DLL vector { class GEODE_DLL vector {
public: public:
using value_type = T; using value_type = T;
auto allocator() const {
return std::allocator<T>();
}
operator std::vector<T>() const { operator std::vector<T>() const {
std::vector<T> out; return std::vector<T>(m_start, m_finish);
for (auto i = m_start; i != m_finish; ++i) {
out.push_back(*i);
}
return out;
} }
vector(std::vector<T> input) { vector() {
std::allocator<T> alloc; m_start = nullptr;
auto tmp = alloc.allocate(input.size()); m_finish = nullptr;
m_reserveEnd = nullptr;
}
m_start = tmp; vector(std::vector<T> const& input) : vector() {
if (input.size()) {
m_start = this->allocator().allocate(input.size());
m_finish = m_start + input.size(); m_finish = m_start + input.size();
m_capacity_end = m_start + input.size(); m_reserveEnd = m_start + input.size();
for (auto i : input) {
*tmp = i; std::copy(input.begin(), input.end(), m_start);
tmp++;
} }
} }
vector(std::initializer_list<T> const& input) { vector(gd::vector<T> const& input) : vector() {
std::allocator<T> alloc; if (input.size()) {
auto tmp = alloc.allocate(input.size()); m_start = this->allocator().allocate(input.size());
m_start = tmp;
m_finish = m_start + input.size(); m_finish = m_start + input.size();
m_capacity_end = m_start + input.size(); m_reserveEnd = m_start + input.size();
std::copy(input.begin(), input.end(), tmp);
std::copy(input.begin(), input.end(), m_start);
}
}
vector(gd::vector<T>&& input) : vector() {
m_start = input.m_start;
m_finish = input.m_finish;
m_reserveEnd = input.m_reserveEnd;
input.m_start = nullptr;
input.m_finish = nullptr;
input.m_reserveEnd = nullptr;
}
vector& operator=(gd::vector<T> const& input) {
this->clear();
if (input.size()) {
m_start = this->allocator().allocate(input.size());
m_finish = m_start + input.size();
m_reserveEnd = m_start + input.size();
std::copy(input.begin(), input.end(), m_start);
}
return *this;
}
vector& operator=(gd::vector<T>&& input) {
m_start = input.m_start;
m_finish = input.m_finish;
m_reserveEnd = input.m_reserveEnd;
input.m_start = nullptr;
input.m_finish = nullptr;
input.m_reserveEnd = nullptr;
return *this;
}
vector(std::initializer_list<T> const& input) : vector() {
if (input.size()) {
m_start = this->allocator().allocate(input.size());
m_finish = m_start + input.size();
m_reserveEnd = m_start + input.size();
std::copy(input.begin(), input.end(), m_start);
}
} }
void clear() { void clear() {
std::allocator<T> alloc; if (m_start) {
alloc.deallocate(m_start, (m_finish - m_start) / 8); std::destroy(m_start, m_finish);
m_start = 0;
m_finish = 0; this->allocator().deallocate(m_start, this->size());
m_capacity_end = 0; }
m_start = nullptr;
m_finish = nullptr;
m_reserveEnd = nullptr;
}
T& operator[](size_t index) {
return m_start[index];
}
T const& operator[](size_t index) const {
return m_start[index];
}
T& at(size_t index) {
if (index >= this->size()) {
throw std::out_of_range("gd::vector::at");
}
return m_start[index];
}
T const& at(size_t index) const {
if (index >= this->size()) {
throw std::out_of_range("gd::vector::at");
}
return m_start[index];
} }
T& front() { T& front() {
return *m_start; return *m_start;
} }
auto begin() { T* begin() {
return m_start; return m_start;
} }
auto end() { T* end() {
return m_finish; return m_finish;
} }
auto begin() const { T const* begin() const {
return static_cast<const T*>(m_start); return m_start;
} }
auto end() const { T const* end() const {
return static_cast<const T*>(m_finish); return m_finish;
} }
vector(vector const& lol) : vector(std::vector<T>(lol)) {}
vector() : vector(std::vector<T>()) {}
~vector() { ~vector() {
for (auto i = m_start; i != m_finish; ++i) { for (auto i = m_start; i != m_finish; ++i) {
delete i; delete i;
} }
} }
size_t size() const {
return m_finish - m_start;
}
size_t capacity() const {
return m_reserveEnd - m_start;
}
protected: protected:
T* m_start; T* m_start;
T* m_finish; T* m_finish;
T* m_capacity_end; T* m_reserveEnd;
}; };
struct _bit_reference { struct _bit_reference {
@ -444,24 +526,32 @@ namespace gd {
uintptr_t* m_capacity_end; uintptr_t* m_capacity_end;
public: public:
vector(std::vector<bool> input) : m_start(0), m_end(0) { auto allocator() const {
auto realsize = input.size() / int(sizeof(uintptr_t)); return std::allocator<uintptr_t>();
auto tmp = new uintptr_t[realsize];
m_start = _bit_iterator(tmp);
m_end = _bit_iterator(tmp + realsize, input.size() % sizeof(uintptr_t));
m_capacity_end = tmp + realsize;
auto itmp = m_start;
for (auto i : input) {
*itmp = i;
++itmp;
}
} }
vector(vector<bool> const& lol) : vector(std::vector<bool>(lol)) {} vector() : m_start(nullptr), m_end(nullptr), m_capacity_end(nullptr) {}
vector() : vector(std::vector<bool>()) {} // vector(std::vector<bool> input) : vector() {
// auto realsize = input.size() / int(sizeof(uintptr_t));
// auto start = this->allocator().allocate(realsize);
// m_start = _bit_iterator(start);
// m_end = _bit_iterator(start + realsize, input.size() % sizeof(uintptr_t));
// m_capacity_end = start + realsize;
// auto itmp = m_start;
// for (auto i : input) {
// *itmp = i;
// ++itmp;
// }
// }
// vector(vector<bool> const& input) : vector() {
// }
// vector() : vector(std::vector<bool>()) {}
~vector() { ~vector() {
delete[] m_start.m_bitptr; delete[] m_start.m_bitptr;
@ -476,8 +566,8 @@ namespace gd {
} }
_bit_reference operator[](size_t index) { _bit_reference operator[](size_t index) {
const auto real_index = index / sizeof(uintptr_t); auto const real_index = index / sizeof(uintptr_t);
const auto offset = index % sizeof(uintptr_t); auto const offset = index % sizeof(uintptr_t);
return _bit_reference(&m_start.m_bitptr[real_index], 1UL << offset); return _bit_reference(&m_start.m_bitptr[real_index], 1UL << offset);
} }

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,6 @@
#pragma once #pragma once
#include "../utils/casts.hpp"
#include "Mod.hpp" #include "Mod.hpp"
#include <Geode/DefaultInclude.hpp> #include <Geode/DefaultInclude.hpp>
@ -45,8 +46,7 @@ namespace geode {
}; };
template <typename T> template <typename T>
concept is_filter = concept is_filter = std::is_base_of_v<EventFilter<typename T::Event>, T> &&
std::is_base_of_v<EventFilter<typename T::Event>, T> &&
requires(T a) { requires(T a) {
a.handle(std::declval<typename T::Callback>(), std::declval<typename T::Event*>()); a.handle(std::declval<typename T::Callback>(), std::declval<typename T::Event*>());
}; };
@ -55,11 +55,13 @@ namespace geode {
class EventListener : public EventListenerProtocol { class EventListener : public EventListenerProtocol {
public: public:
using Callback = typename T::Callback; using Callback = typename T::Callback;
template <typename C> requires std::is_class_v<C> template <typename C>
requires std::is_class_v<C>
using MemberFn = typename to_member<C, Callback>::value; using MemberFn = typename to_member<C, Callback>::value;
ListenerResult passThrough(Event* e) override { ListenerResult passThrough(Event* e) override {
if (auto myev = dynamic_cast<typename T::Event*>(e)) { // it is so silly to use dynamic cast in an interbinary context
if (auto myev = cast::typeinfo_cast<typename T::Event*>(e)) {
return m_filter.handle(m_callback, myev); return m_filter.handle(m_callback, myev);
} }
return ListenerResult::Propagate; return ListenerResult::Propagate;
@ -68,25 +70,31 @@ namespace geode {
EventListener(T filter = T()) { EventListener(T filter = T()) {
this->enable(); this->enable();
} }
EventListener(std::function<Callback> fn, T filter = T()) : m_callback(fn), m_filter(filter) {
EventListener(std::function<Callback> fn, T filter = T()) :
m_callback(fn), m_filter(filter) {
this->enable(); this->enable();
} }
EventListener(Callback* fnptr, T filter = T()) : m_callback(fnptr), m_filter(filter) { EventListener(Callback* fnptr, T filter = T()) : m_callback(fnptr), m_filter(filter) {
this->enable(); this->enable();
} }
template <class C> template <class C>
EventListener(C* cls, MemberFn<C> fn, T filter = T()) : EventListener(std::bind(fn, cls, std::placeholders::_1), filter) { EventListener(C* cls, MemberFn<C> fn, T filter = T()) :
EventListener(std::bind(fn, cls, std::placeholders::_1), filter) {
this->enable(); this->enable();
} }
void bind(std::function<Callback> fn) { void bind(std::function<Callback> fn) {
m_callback = fn; m_callback = fn;
} }
template <typename C> template <typename C>
void bind(C* cls, MemberFn<C> fn) { void bind(C* cls, MemberFn<C> fn) {
m_callback = std::bind(fn, cls, std::placeholders::_1); m_callback = std::bind(fn, cls, std::placeholders::_1);
} }
protected: protected:
std::function<Callback> m_callback; std::function<Callback> m_callback;
T m_filter; T m_filter;
@ -96,6 +104,7 @@ namespace geode {
static std::unordered_set<EventListenerProtocol*> s_listeners; static std::unordered_set<EventListenerProtocol*> s_listeners;
Mod* m_sender; Mod* m_sender;
friend EventListenerProtocol; friend EventListenerProtocol;
public: public:
void postFrom(Mod* sender); void postFrom(Mod* sender);

View file

@ -1,9 +1,10 @@
#pragma once #pragma once
#include "Event.hpp" #include "Event.hpp"
#include <optional>
#include "Mod.hpp" #include "Mod.hpp"
#include <optional>
namespace geode { namespace geode {
enum class ModEventType { enum class ModEventType {
Loaded, Loaded,
@ -45,13 +46,17 @@ void GEODE_CONCAT(geodeExecFunction, __LINE__)(ModStateEvent*); \
namespace { \ namespace { \
struct GEODE_CONCAT(ExecFuncUnique, __LINE__) {}; \ struct GEODE_CONCAT(ExecFuncUnique, __LINE__) {}; \
} \ } \
static inline auto GEODE_CONCAT(Exec, __LINE__) = (geode::Loader::get()->scheduleOnModLoad(\ static inline auto GEODE_CONCAT(Exec, __LINE__) = \
geode::Mod::get(), []() { \ (geode::Loader::get()->scheduleOnModLoad( \
geode::Mod::get(), \
[]() { \
static auto _ = geode::EventListener( \ static auto _ = geode::EventListener( \
&GEODE_CONCAT(geodeExecFunction, __LINE__)<GEODE_CONCAT(ExecFuncUnique, __LINE__)>,\ &GEODE_CONCAT(geodeExecFunction, __LINE__) < \
GEODE_CONCAT(ExecFuncUnique, __LINE__) >, \
geode::ModStateFilter(geode::Mod::get(), geode::ModEventType::type) \ geode::ModStateFilter(geode::Mod::get(), geode::ModEventType::type) \
); \ ); \
} \ } \
), 0); \ ), \
0); \
template <class> \ template <class> \
void GEODE_CONCAT(geodeExecFunction, __LINE__)(ModStateEvent*) void GEODE_CONCAT(geodeExecFunction, __LINE__)(ModStateEvent*)

View file

@ -42,16 +42,13 @@ namespace geode::modifier {
} }
}; };
GEODE_DLL size_t getFieldIndexForClass(size_t hash);
template <class Parent, class Base> template <class Parent, class Base>
class FieldIntermediate { class FieldIntermediate {
// Padding used for guaranteeing any member of parents // Padding used for guaranteeing any member of parents
// will be in between sizeof(Intermediate) and sizeof(Parent) // will be in between sizeof(Intermediate) and sizeof(Parent)
uintptr_t m_padding; uintptr_t m_padding;
static inline std::unordered_map<size_t, size_t> nextIndex;
static size_t getFieldIndexForClass(size_t hash) {
return nextIndex[hash]++;
}
public: public:
static void fieldConstructor(void* offsetField) { static void fieldConstructor(void* offsetField) {

View file

@ -55,21 +55,3 @@
* Useful for callbacks * Useful for callbacks
*/ */
#define $cls std::remove_pointer<decltype(this)>::type #define $cls std::remove_pointer<decltype(this)>::type
#define GEODE_ONLY_FIELD(type, field_, default_) private: field<type> field_ = default_; public:
#define GEODE_INTERNAL_FIELD(type, field, name) inline type& name() { return this->*field; }
//#define GEODE_EXTERNAL_FIELD(type, field, name) static inline type& name##From(void* self) { return reinterpret_cast<decltype(this)>(self)->*field; }
#define GEODE_FIELD(type, field, name, default_) GEODE_ONLY_FIELD(type, field, default_) GEODE_INTERNAL_FIELD(type, field, name) //GEODE_EXTERNAL_FIELD(type, field, name)
#define $execute \
template<class> \
void GEODE_CONCAT(geodeExecFunction, __LINE__)(); \
namespace { \
struct GEODE_CONCAT(ExecFuncUnique, __LINE__) {}; \
} \
static inline auto GEODE_CONCAT(Exec, __LINE__) = (Loader::get()->scheduleOnModLoad(\
nullptr, &GEODE_CONCAT(geodeExecFunction, __LINE__)<GEODE_CONCAT(ExecFuncUnique, __LINE__)> \
), 0); \
template<class> \
void GEODE_CONCAT(geodeExecFunction, __LINE__)()

View file

@ -1,7 +1,7 @@
#pragma once #pragma once
#include "../loader/Log.hpp"
#include "../external/json/json.hpp" #include "../external/json/json.hpp"
#include "../loader/Log.hpp"
#include <set> #include <set>
#include <variant> #include <variant>
@ -15,9 +15,7 @@ namespace geode {
template <typename T> template <typename T>
struct is_iterable< struct is_iterable<
T, T, std::void_t<decltype(std::begin(std::declval<T>())), decltype(std::end(std::declval<T>()))>> :
std::void_t<
decltype(std::begin(std::declval<T>())), decltype(std::end(std::declval<T>()))>> :
std::true_type {}; std::true_type {};
template <typename T> template <typename T>
@ -79,7 +77,7 @@ namespace geode {
} }
template <class T> template <class T>
using JsonValueValidator = bool (*)(T const&); using JsonValueValidator = std::function<bool(T const&)>;
template <class Json> template <class Json>
struct JsonMaybeObject; struct JsonMaybeObject;
@ -175,6 +173,11 @@ namespace geode {
return *this; return *this;
} }
template <class T>
JsonMaybeValue<Json>& validate(bool (*validator)(T const&)) {
return this->validate(std::function(validator));
}
template <class T> template <class T>
JsonMaybeValue<Json>& inferType() { JsonMaybeValue<Json>& inferType() {
if (this->isError() || !m_inferType) return *this; if (this->isError() || !m_inferType) return *this;

View file

@ -1,306 +1,216 @@
#pragma once #pragma once
#include "../DefaultInclude.hpp" #include "../DefaultInclude.hpp"
#include "../external/result/result.hpp"
#include <fmt/format.h>
#include <string> #include <string>
#include <string_view> #include <string_view>
#include <type_traits>
#include <variant> #include <variant>
#include <fmt/format.h>
// clang-format off
namespace geode { namespace geode {
namespace { namespace impl {
struct AnyType {
explicit AnyType() = delete;
};
template <class V, class RV>
concept ConvertibleToResult =
std::is_convertible_v<std::remove_reference_t<V>, std::remove_reference_t<RV>> ||
std::is_same_v<std::remove_reference_t<V>, std::remove_reference_t<RV>>;
using DefaultValue = std::monostate; using DefaultValue = std::monostate;
using DefaultError = std::string; using DefaultError = std::string;
template<class T, class E>
struct Storage {
std::variant<T, E> m_value;
bool holdsOk() const {
return std::holds_alternative<T>(m_value);
}
T getOk() const requires std::is_copy_constructible_v<T> {
return std::get<T>(m_value);
}
T&& getOk() requires(!std::is_copy_constructible_v<T>) {
return std::move(std::get<T>(m_value));
}
E getErr() const requires std::is_copy_constructible_v<E> {
return std::get<E>(m_value);
}
E&& getErr() requires(!std::is_copy_constructible_v<E>) {
return std::move(std::get<E>(m_value));
}
template<class T2, class E2>
requires
std::is_convertible_v<T2, T> &&
std::is_convertible_v<E2, E>
Storage(Storage<T2, E2> const& other)
requires
std::is_copy_constructible_v<T> &&
std::is_copy_constructible_v<E>
{
if (other.holdsOk()) {
m_value = other.getOk();
} else {
m_value = other.getErr();
}
}
Storage(T const& value)
requires std::is_copy_constructible_v<T>
: m_value(value) {}
Storage(T&& value)
requires std::is_move_constructible_v<T>
: m_value(std::forward<T>(value)) {}
Storage(E const& value, std::monostate)
requires std::is_copy_constructible_v<E>
: m_value(value) {}
Storage(E&& value, std::monostate)
requires std::is_move_constructible_v<E>
: m_value(std::forward<E>(value)) {}
};
template <class T> template <class T>
struct Storage<T, T> { using WrappedResult = std::conditional_t<
bool m_holdsOk; std::is_lvalue_reference_v<T>, std::reference_wrapper<std::remove_reference_t<T>>,
T m_value; std::remove_const_t<T>>;
bool holdsOk() const { template <class E = impl::DefaultError>
return m_holdsOk; class [[nodiscard]] Failure {
public:
WrappedResult<E> m_error;
Failure() = default;
template <class E2>
requires(std::is_constructible_v<E, E2 const&>)
explicit constexpr Failure(E2 const& e) : m_error(e) {}
template <class E2>
requires(std::is_constructible_v<E, E2 &&>)
explicit constexpr Failure(E2&& e) : m_error(std::move(e)) {}
E& error() & noexcept {
return m_error;
} }
T getOk() const requires std::is_copy_constructible_v<T> { E const& error() const& noexcept {
return m_error;
}
E&& error() && noexcept {
return static_cast<E&&>(m_error);
}
E const&& error() const&& noexcept {
return static_cast<E&&>(m_error);
}
};
template <class T = impl::DefaultValue>
class [[nodiscard]] Success {
public:
WrappedResult<T> m_value;
Success() = default;
template <class T2>
requires(std::is_constructible_v<T, T2 const&>)
explicit constexpr Success(T2 const& v) : m_value(v) {}
template <class T2>
requires(std::is_constructible_v<T, T2 &&>)
explicit constexpr Success(T2&& v) : m_value(std::forward<T2>(v)) {}
T& value() & noexcept {
return m_value; return m_value;
} }
T&& getOk() requires(!std::is_copy_constructible_v<T>) { T const& value() const& noexcept {
return std::move(m_value);
}
T getErr() const requires std::is_copy_constructible_v<T> {
return m_value; return m_value;
} }
T&& getErr() requires(!std::is_copy_constructible_v<T>) { T&& value() && noexcept {
return std::move(m_value); return static_cast<T&&>(m_value);
} }
template<class T2, class E2> T const&& value() const&& noexcept {
requires return static_cast<T&&>(m_value);
std::is_convertible_v<T2, T> && }
std::is_convertible_v<E2, T>
Storage(Storage<T2, E2> const& other)
requires
std::is_copy_constructible_v<T> &&
std::is_copy_constructible_v<T>
: m_value(other.holdsOk() ? other.getOk() : other.getErr()),
m_holdsOk(other.holdsOk()) {}
Storage(T const& value)
requires std::is_copy_constructible_v<T>
: m_value(value),
m_holdsOk(true) {}
Storage(T&& value)
requires std::is_move_constructible_v<T>
: m_value(std::forward<T>(value)),
m_holdsOk(true) {}
Storage(T const& value, std::monostate)
requires std::is_copy_constructible_v<T>
: m_value(value),
m_holdsOk(false) {}
Storage(T&& value, std::monostate)
requires std::is_move_constructible_v<T>
: m_value(std::forward<T>(value)),
m_holdsOk(false) {}
}; };
} }
template <class T = DefaultValue, class E = DefaultError> template <class T = impl::DefaultValue, class E = impl::DefaultError>
class [[nodiscard]] Result final { class [[nodiscard]] Result : public cpp::result<T, E> {
public: public:
using value_type = std::remove_reference_t<T>; using Base = cpp::result<T, E>;
using error_type = std::remove_reference_t<E>; using ValueType = typename Base::value_type;
using ErrorType = typename Base::error_type;
// for some reason doing requires causes errors with pch... using Base::result;
static_assert(
std::is_copy_constructible_v<value_type> || std::is_move_constructible_v<value_type>,
"T must be copiable or movable!"
);
static_assert(
std::is_copy_constructible_v<error_type> || std::is_move_constructible_v<error_type>,
"E must be copiable or movable!"
);
protected: template <class U>
Storage<value_type, error_type> m_value; requires(cpp::detail::result_is_implicit_value_convertible<T, U>::value)
constexpr Result(U&& value) = delete;
public: template <class E2>
Storage<value_type, error_type> const& _Raw_Storage() const { requires(std::is_constructible_v<E, E2 const&>)
return m_value; constexpr Result(impl::Failure<E2> const& e) : Base(cpp::failure<E>(e.error())) {}
template <class E2>
requires(std::is_constructible_v<E, E2 &&>)
constexpr Result(impl::Failure<E2>&& e) : Base(cpp::failure<E>(std::move(e.error()))) {}
template <class T2>
requires(std::is_constructible_v<T, T2 const&>)
constexpr Result(impl::Success<T2> const& s) : Base(s.value()) {}
template <class T2>
requires(std::is_constructible_v<T, T2 &&>)
constexpr Result(impl::Success<T2>&& s) : Base(std::move(s.value())) {}
[[nodiscard]] constexpr explicit operator bool() const noexcept {
return this->Base::operator bool();
} }
bool isOk() const { [[nodiscard]] constexpr bool isOk() const noexcept {
return m_value.holdsOk(); return this->Base::has_value();
} }
bool isErr() const { [[nodiscard]] constexpr bool isErr() const noexcept {
return !m_value.holdsOk(); return this->Base::has_error();
}
[[nodiscard]] constexpr decltype(auto) unwrap() & {
return this->Base::value();
}
[[nodiscard]] constexpr decltype(auto) unwrap() const& {
return this->Base::value();
}
[[nodiscard]] constexpr decltype(auto) unwrap() && {
return this->Base::value();
}
[[nodiscard]] constexpr decltype(auto) unwrap() const&& {
return this->Base::value();
}
[[nodiscard]] constexpr decltype(auto) unwrapErr() & {
return this->Base::error();
}
[[nodiscard]] constexpr decltype(auto) unwrapErr() const& {
return this->Base::error();
}
[[nodiscard]] constexpr decltype(auto) unwrapErr() && {
return this->Base::error();
}
[[nodiscard]] constexpr decltype(auto) unwrapErr() const&& {
return this->Base::error();
} }
template <class... Args> template <class... Args>
Result<T, std::string> expect(const char* str, Args&&... args) { [[nodiscard]] Result<T, std::string> expect(std::string const& format, Args&&... args)
if (isErr()) { const {
return Result<T, std::string>(fmt::format( if (this->isErr()) {
str, return impl::Failure<std::string>(fmt::format(
std::forward<Args>(args)..., fmt::runtime(format), std::forward<Args>(args)...,
fmt::arg("error", unwrapErr()) fmt::arg("error", this->unwrapErr())
), std::monostate()); ));
} else { }
else {
return *this; return *this;
} }
} }
explicit Result(value_type const& value) template <class U>
requires std::is_copy_constructible_v<value_type> [[nodiscard]] constexpr decltype(auto) unwrapOr(U&& val) && {
: m_value(value) {} return this->Base::value_or(std::forward<U>(val));
explicit Result(value_type&& value)
requires std::is_move_constructible_v<value_type>
: m_value(std::forward<value_type>(value)) {}
explicit Result(error_type const& value, std::monostate)
requires std::is_copy_constructible_v<error_type>
: m_value(value, std::monostate()) {}
explicit Result(error_type&& value, std::monostate)
requires std::is_move_constructible_v<error_type>
: m_value(std::forward<error_type>(value), std::monostate()) {}
Result(Result<T, E> const& other)
requires
std::is_copy_constructible_v<value_type> &&
std::is_copy_constructible_v<error_type>
= default;
Result(Result<T, E>&& other)
requires(
!std::is_copy_constructible_v<value_type> ||
!std::is_copy_constructible_v<error_type>
) = default;
template<class T2, class E2>
requires
std::is_convertible_v<T2, T> &&
std::is_convertible_v<E2, E>
Result(Result<T2, E2> const& other)
requires
std::is_copy_constructible_v<value_type> &&
std::is_copy_constructible_v<error_type>
: m_value(other._Raw_Storage()) {}
template <class T2>
requires ConvertibleToResult<T2, T>
Result(Result<T2, AnyType> const& other)
requires
std::is_copy_constructible_v<value_type> &&
std::is_copy_constructible_v<error_type>
: Result(value_type(other.unwrap())) {}
template <class E2>
requires ConvertibleToResult<E2, E>
Result(Result<AnyType, E2> const& other)
requires
std::is_copy_constructible_v<value_type> &&
std::is_copy_constructible_v<error_type>
: m_value(std::forward<E2>(other.unwrapErr()), std::monostate()) {}
template <class T2>
requires ConvertibleToResult<T2, T>
Result(Result<T2, AnyType>&& other)
requires(
!std::is_copy_constructible_v<value_type> ||
!std::is_copy_constructible_v<error_type>
)
: m_value(other.unwrap()) {}
template <class E2>
requires ConvertibleToResult<E2, E>
Result(Result<AnyType, E2>&& other)
requires(
!std::is_copy_constructible_v<value_type> ||
!std::is_copy_constructible_v<error_type>
)
: Result(std::forward<error_type>(other.unwrapErr()), std::monostate()) {}
value_type unwrap() const requires std::is_copy_constructible_v<value_type> {
return m_value.getOk();
} }
value_type&& unwrap() requires(!std::is_copy_constructible_v<value_type>) { template <class U>
return std::forward<value_type>(m_value.getOk()); [[nodiscard]] constexpr decltype(auto) unwrapOr(U&& val) const& {
return this->Base::value_or(std::forward<U>(val));
} }
error_type unwrapErr() const requires std::is_copy_constructible_v<error_type> { template <class U>
return m_value.getErr(); [[nodiscard]] constexpr decltype(auto) errorOr(U&& val) && {
return this->Base::error_or(std::forward<U>(val));
} }
error_type&& unwrapErr() requires(!std::is_copy_constructible_v<error_type>) { template <class U>
return std::forward<error_type>(m_value.getErr()); [[nodiscard]] constexpr decltype(auto) errorOr(U&& val) const& {
} return this->Base::error_or(std::forward<U>(val));
explicit operator bool() const requires(
!std::is_same_v<T, bool> &&
!std::is_same_v<E, bool>
) {
return this->isOk();
} }
}; };
template <class T = DefaultValue, class E = AnyType> template <class T = impl::DefaultValue>
requires std::is_copy_constructible_v<T> constexpr impl::Success<T> Ok() {
Result<T, E> Ok(T value = T()) { return impl::Success<T>();
return Result<T, E>(value);
} }
template <class T = DefaultValue, class E = AnyType> template <class T>
requires(!std::is_copy_constructible_v<T>) constexpr impl::Success<T> Ok(T&& value) {
Result<T, E> Ok(T&& value) { return impl::Success<T>(std::forward<T>(value));
return Result<T, E>(std::forward<T>(value));
} }
template <class E = DefaultError, class T = AnyType> template <class E>
requires std::is_copy_constructible_v<E> constexpr impl::Failure<E> Err(E&& error) {
Result<T, E> Err(E error) { return impl::Failure<E>(std::forward<E>(error));
return Result<T, E>(error, std::monostate());
} }
template <class E = DefaultError, class T = AnyType> template <class... Args>
requires(!std::is_copy_constructible_v<E>) inline impl::Failure<std::string> Err(std::string const& format, Args&&... args) {
Result<T, E> Err(E&& error) { return impl::Failure<std::string>(
return Result<T, E>(std::forward<E>(error), std::monostate()); fmt::format(fmt::runtime(format), std::forward<Args>(args)...)
);
} }
#define GEODE_UNWRAP_INTO(into, ...) \ #define GEODE_UNWRAP_INTO(into, ...) \
@ -318,5 +228,3 @@ namespace geode {
} \ } \
} }
} }
// clang-format on

View file

@ -1,8 +1,9 @@
#pragma once #pragma once
#include "casts.hpp"
#include "../external/json/json.hpp" #include "../external/json/json.hpp"
#include "casts.hpp"
#include "general.hpp" #include "general.hpp"
#include <Geode/DefaultInclude.hpp> #include <Geode/DefaultInclude.hpp>
#include <cocos2d.h> #include <cocos2d.h>
#include <functional> #include <functional>
@ -283,6 +284,7 @@ namespace geode {
bool operator==(T* other) const { bool operator==(T* other) const {
return m_obj == other; return m_obj == other;
} }
bool operator==(Ref<T> const& other) const { bool operator==(Ref<T> const& other) const {
return m_obj == other.m_obj; return m_obj == other.m_obj;
} }
@ -290,6 +292,7 @@ namespace geode {
bool operator!=(T* other) const { bool operator!=(T* other) const {
return m_obj != other; return m_obj != other;
} }
bool operator!=(Ref<T> const& other) const { bool operator!=(Ref<T> const& other) const {
return m_obj != other.m_obj; return m_obj != other.m_obj;
} }
@ -298,6 +301,7 @@ namespace geode {
bool operator<(Ref<T> const& other) const { bool operator<(Ref<T> const& other) const {
return m_obj < other.m_obj; return m_obj < other.m_obj;
} }
bool operator>(Ref<T> const& other) const { bool operator>(Ref<T> const& other) const {
return m_obj > other.m_obj; return m_obj > other.m_obj;
} }
@ -435,7 +439,7 @@ namespace geode::cocos {
*/ */
GEODE_DLL cocos2d::CCScene* switchToScene(cocos2d::CCLayer* layer); GEODE_DLL cocos2d::CCScene* switchToScene(cocos2d::CCLayer* layer);
using CreateLayerFunc = cocos2d::CCLayer*(*)(); using CreateLayerFunc = std::function<cocos2d::CCLayer*()>;
/** /**
* Reload textures, overwriting the scene to return to after the loading * Reload textures, overwriting the scene to return to after the loading
@ -453,9 +457,7 @@ namespace geode::cocos {
* @param def Default size * @param def Default size
* @param min Minimum size * @param min Minimum size
*/ */
GEODE_DLL void limitNodeSize( GEODE_DLL void limitNodeSize(cocos2d::CCNode* node, cocos2d::CCSize const& size, float def, float min);
cocos2d::CCNode* node, cocos2d::CCSize const& size, float def, float min
);
/** /**
* Checks if a node is visible (recursively * Checks if a node is visible (recursively
@ -497,8 +499,7 @@ namespace geode::cocos {
for (int i = 0; i < children->count(); ++i) { for (int i = 0; i < children->count(); ++i) {
auto newParent = static_cast<cocos2d::CCNode*>(children->objectAtIndex(i)); auto newParent = static_cast<cocos2d::CCNode*>(children->objectAtIndex(i));
auto child = findFirstChildRecursive(newParent, predicate); auto child = findFirstChildRecursive(newParent, predicate);
if (child) if (child) return child;
return child;
} }
return nullptr; return nullptr;
@ -602,12 +603,17 @@ namespace geode::cocos {
} }
inline cocos2d::ccColor4B invert4B(cocos2d::ccColor4B const& color) { inline cocos2d::ccColor4B invert4B(cocos2d::ccColor4B const& color) {
return { static_cast<GLubyte>(255 - color.r), static_cast<GLubyte>(255 - color.g), return {
static_cast<GLubyte>(255 - color.b), color.a }; static_cast<GLubyte>(255 - color.r),
static_cast<GLubyte>(255 - color.g),
static_cast<GLubyte>(255 - color.b),
color.a};
} }
inline cocos2d::ccColor3B invert3B(cocos2d::ccColor3B const& color) { inline cocos2d::ccColor3B invert3B(cocos2d::ccColor3B const& color) {
return { static_cast<GLubyte>(255 - color.r), static_cast<GLubyte>(255 - color.g), return {
static_cast<GLubyte>(255 - color.r),
static_cast<GLubyte>(255 - color.g),
static_cast<GLubyte>(255 - color.b)}; static_cast<GLubyte>(255 - color.b)};
} }
@ -637,19 +643,23 @@ namespace geode::cocos {
constexpr cocos2d::ccColor3B cc3x(int hexValue) { constexpr cocos2d::ccColor3B cc3x(int hexValue) {
if (hexValue <= 0xf) if (hexValue <= 0xf)
return cocos2d::ccColor3B { static_cast<GLubyte>(hexValue * 17), return cocos2d::ccColor3B{
static_cast<GLubyte>(hexValue * 17),
static_cast<GLubyte>(hexValue * 17), static_cast<GLubyte>(hexValue * 17),
static_cast<GLubyte>(hexValue * 17)}; static_cast<GLubyte>(hexValue * 17)};
if (hexValue <= 0xff) if (hexValue <= 0xff)
return cocos2d::ccColor3B { static_cast<GLubyte>(hexValue), return cocos2d::ccColor3B{
static_cast<GLubyte>(hexValue),
static_cast<GLubyte>(hexValue), static_cast<GLubyte>(hexValue),
static_cast<GLubyte>(hexValue)}; static_cast<GLubyte>(hexValue)};
if (hexValue <= 0xfff) if (hexValue <= 0xfff)
return cocos2d::ccColor3B { static_cast<GLubyte>((hexValue >> 8 & 0xf) * 17), return cocos2d::ccColor3B{
static_cast<GLubyte>((hexValue >> 8 & 0xf) * 17),
static_cast<GLubyte>((hexValue >> 4 & 0xf) * 17), static_cast<GLubyte>((hexValue >> 4 & 0xf) * 17),
static_cast<GLubyte>((hexValue >> 0 & 0xf) * 17)}; static_cast<GLubyte>((hexValue >> 0 & 0xf) * 17)};
else else
return cocos2d::ccColor3B { static_cast<GLubyte>(hexValue >> 16 & 0xff), return cocos2d::ccColor3B{
static_cast<GLubyte>(hexValue >> 16 & 0xff),
static_cast<GLubyte>(hexValue >> 8 & 0xff), static_cast<GLubyte>(hexValue >> 8 & 0xff),
static_cast<GLubyte>(hexValue >> 0 & 0xff)}; static_cast<GLubyte>(hexValue >> 0 & 0xff)};
} }
@ -668,9 +678,7 @@ namespace geode::cocos {
} }
template <typename T, typename C, typename = std::enable_if_t<std::is_pointer_v<C>>> template <typename T, typename C, typename = std::enable_if_t<std::is_pointer_v<C>>>
static cocos2d::CCArray* vectorToCCArray( static cocos2d::CCArray* vectorToCCArray(std::vector<T> const& vec, std::function<C(T)> convFunc) {
std::vector<T> const& vec, std::function<C(T)> convFunc
) {
auto res = cocos2d::CCArray::createWithCapacity(vec.size()); auto res = cocos2d::CCArray::createWithCapacity(vec.size());
for (auto const& item : vec) for (auto const& item : vec)
res->addObject(convFunc(item)); res->addObject(convFunc(item));
@ -680,8 +688,7 @@ namespace geode::cocos {
template <typename T, typename = std::enable_if_t<std::is_pointer_v<T>>> template <typename T, typename = std::enable_if_t<std::is_pointer_v<T>>>
std::vector<T> ccArrayToVector(cocos2d::CCArray* arr) { std::vector<T> ccArrayToVector(cocos2d::CCArray* arr) {
return std::vector<T>( return std::vector<T>(
reinterpret_cast<T*>(arr->data->arr), reinterpret_cast<T*>(arr->data->arr), reinterpret_cast<T*>(arr->data->arr) + arr->data->num
reinterpret_cast<T*>(arr->data->arr) + arr->data->num
); );
} }
@ -698,9 +705,7 @@ namespace geode::cocos {
template < template <
typename K, typename V, typename C, typename K, typename V, typename C,
typename = std::enable_if_t<std::is_same_v<C, std::string> || std::is_same_v<C, intptr_t>>> typename = std::enable_if_t<std::is_same_v<C, std::string> || std::is_same_v<C, intptr_t>>>
static cocos2d::CCDictionary* mapToCCDict( static cocos2d::CCDictionary* mapToCCDict(std::map<K, V> const& map, std::function<C(K)> convFunc) {
std::map<K, V> const& map, std::function<C(K)> convFunc
) {
auto res = cocos2d::CCDictionary::create(); auto res = cocos2d::CCDictionary::create();
for (auto const& [key, value] : map) for (auto const& [key, value] : map)
res->setObject(value, convFunc(key)); res->setObject(value, convFunc(key));
@ -797,6 +802,7 @@ namespace geode::cocos {
} }
return CCArrayIterator<T*>(reinterpret_cast<T**>(m_arr->data->arr) + m_arr->count()); return CCArrayIterator<T*>(reinterpret_cast<T**>(m_arr->data->arr) + m_arr->count());
} }
size_t size() const { size_t size() const {
return m_arr ? m_arr->count() : 0; return m_arr ? m_arr->count() : 0;
} }

View file

@ -1,8 +1,8 @@
#pragma once #pragma once
#include "../DefaultInclude.hpp" #include "../DefaultInclude.hpp"
#include "Result.hpp"
#include "../external/json/json.hpp" #include "../external/json/json.hpp"
#include "Result.hpp"
#include "general.hpp" #include "general.hpp"
#include <fs/filesystem.hpp> #include <fs/filesystem.hpp>
@ -38,8 +38,7 @@ namespace geode::utils::web {
* @returns Returned data as JSON, or error on error * @returns Returned data as JSON, or error on error
*/ */
GEODE_DLL Result<> fetchFile( GEODE_DLL Result<> fetchFile(
std::string const& url, ghc::filesystem::path const& into, std::string const& url, ghc::filesystem::path const& into, FileProgressCallback prog = nullptr
FileProgressCallback prog = nullptr
); );
/** /**

View file

@ -2,7 +2,8 @@
Version 1.1, February 14h, 2010 Version 1.1, February 14h, 2010
part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) Copyright (C) 1998-2010 Gilles Vollant (minizip) (
http://www.winimage.com/zLibDll/minizip.html )
Modifications for Zip64 support Modifications for Zip64 support
Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
@ -12,15 +13,17 @@
Changes Changes
Oct-2009 - Mathias Svensson - Remove old C style function prototypes Oct-2009 - Mathias Svensson - Remove old C style function prototypes
Oct-2009 - Mathias Svensson - Added Zip64 Support when creating new file archives Oct-2009 - Mathias Svensson - Added Zip64 Support when creating new file archives
Oct-2009 - Mathias Svensson - Did some code cleanup and refactoring to get better overview of some functions. Oct-2009 - Mathias Svensson - Did some code cleanup and refactoring to get better overview of
Oct-2009 - Mathias Svensson - Added zipRemoveExtraInfoBlock to strip extra field data from its ZIP64 data some functions. Oct-2009 - Mathias Svensson - Added zipRemoveExtraInfoBlock to strip extra field
It is used when recreting zip archive with RAW when deleting items from a zip. data from its ZIP64 data It is used when recreting zip archive with RAW when deleting items from
ZIP64 data is automatically added to items that needs it, and existing ZIP64 data need to be removed. a zip. ZIP64 data is automatically added to items that needs it, and existing ZIP64 data need to
Oct-2009 - Mathias Svensson - Added support for BZIP2 as compression mode (bzip2 lib is required) be removed. Oct-2009 - Mathias Svensson - Added support for BZIP2 as compression mode (bzip2 lib
Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer is required) Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer
*/ */
// clang-format off
#ifndef NOCRYPT #ifndef NOCRYPT
#define NOCRYPT #define NOCRYPT
#endif #endif
@ -1071,7 +1074,7 @@ extern int ZEXPORT zipOpenNewFileInZip4_64 (zipFile file, const char* filename,
int err = ZIP_OK; int err = ZIP_OK;
# ifdef NOCRYPT # ifdef NOCRYPT
(crcForCrypting); (void)(crcForCrypting);
if (password != NULL) if (password != NULL)
return ZIP_PARAMERROR; return ZIP_PARAMERROR;
# endif # endif
@ -2006,3 +2009,5 @@ extern int ZEXPORT zipRemoveExtraInfoBlock (char* pData, int* dataLen, short sHe
} }
} // end of namespace cocos2d } // end of namespace cocos2d
// clang-format on

View file

@ -64,7 +64,6 @@ public:
}; };
// proxy forwards // proxy forwards
// clang-format off
#include <Geode/modify/CCNode.hpp> #include <Geode/modify/CCNode.hpp>
struct ProxyCCNode : Modify<ProxyCCNode, CCNode> { struct ProxyCCNode : Modify<ProxyCCNode, CCNode> {
virtual CCObject* getUserObject() { virtual CCObject* getUserObject() {
@ -80,7 +79,10 @@ struct ProxyCCNode : Modify<ProxyCCNode, CCNode> {
} }
}; };
// clang-format on static inline std::unordered_map<size_t, size_t> s_nextIndex;
size_t modifier::getFieldIndexForClass(size_t hash) {
return s_nextIndex[hash]++;
}
// not const because might modify contents // not const because might modify contents
FieldContainer* CCNode::getFieldContainer() { FieldContainer* CCNode::getFieldContainer() {

View file

@ -20,10 +20,10 @@ Result<> Hook::enable() {
m_enabled = true; m_enabled = true;
m_handle = res.unwrap(); m_handle = res.unwrap();
return Ok(); return Ok();
} else { }
else {
return Err( return Err(
"Unable to create hook at " + "Unable to create hook at " + std::to_string(reinterpret_cast<uintptr_t>(m_address))
std::to_string(reinterpret_cast<uintptr_t>(m_address))
); );
} }
return Err("Hook already has a handle"); return Err("Hook already has a handle");
@ -33,8 +33,7 @@ Result<> Hook::enable() {
Result<> Hook::disable() { Result<> Hook::disable() {
if (m_enabled) { if (m_enabled) {
if (!geode::core::hook::remove(m_handle)) if (!geode::core::hook::remove(m_handle)) return Err("Unable to remove hook");
return Err("Unable to remove hook");
log::debug("Disabling hook at function {}", m_displayName); log::debug("Disabling hook at function {}", m_displayName);
m_enabled = false; m_enabled = false;

View file

@ -1,20 +1,17 @@
#include <string>
#include <optional>
#include <vector>
#include <Geode/loader/Mod.hpp>
#include <Geode/loader/Hook.hpp> #include <Geode/loader/Hook.hpp>
#include <Geode/loader/Mod.hpp>
#include <Geode/utils/file.hpp> #include <Geode/utils/file.hpp>
#include <InternalLoader.hpp> #include <InternalLoader.hpp>
#include <InternalMod.hpp> #include <InternalMod.hpp>
#include <optional>
#include <string>
#include <vector>
USE_GEODE_NAMESPACE(); USE_GEODE_NAMESPACE();
Mod::Mod(ModInfo const& info) { Mod::Mod(ModInfo const& info) {
m_info = info; m_info = info;
m_saveDirPath = Loader::get()->getGeodeSaveDirectory() / m_saveDirPath = Loader::get()->getGeodeSaveDirectory() / GEODE_MOD_DIRECTORY / info.m_id;
GEODE_MOD_DIRECTORY / info.m_id;
ghc::filesystem::create_directories(m_saveDirPath); ghc::filesystem::create_directories(m_saveDirPath);
} }
@ -27,57 +24,75 @@ Mod::~Mod() {
ghc::filesystem::path Mod::getSaveDir() const { ghc::filesystem::path Mod::getSaveDir() const {
return m_saveDirPath; return m_saveDirPath;
} }
std::string Mod::getID() const { std::string Mod::getID() const {
return m_info.m_id; return m_info.m_id;
} }
std::string Mod::getName() const { std::string Mod::getName() const {
return m_info.m_name; return m_info.m_name;
} }
std::string Mod::getDeveloper() const { std::string Mod::getDeveloper() const {
return m_info.m_developer; return m_info.m_developer;
} }
std::optional<std::string> Mod::getDescription() const { std::optional<std::string> Mod::getDescription() const {
return m_info.m_description; return m_info.m_description;
} }
std::optional<std::string> Mod::getDetails() const { std::optional<std::string> Mod::getDetails() const {
return m_info.m_details; return m_info.m_details;
} }
ModInfo Mod::getModInfo() const { ModInfo Mod::getModInfo() const {
return m_info; return m_info;
} }
ghc::filesystem::path Mod::getTempDir() const { ghc::filesystem::path Mod::getTempDir() const {
return m_tempDirName; return m_tempDirName;
} }
ghc::filesystem::path Mod::getBinaryPath() const { ghc::filesystem::path Mod::getBinaryPath() const {
return m_tempDirName / m_info.m_binaryName; return m_tempDirName / m_info.m_binaryName;
} }
ghc::filesystem::path Mod::getPackagePath() const { ghc::filesystem::path Mod::getPackagePath() const {
return m_info.m_path; return m_info.m_path;
} }
VersionInfo Mod::getVersion() const { VersionInfo Mod::getVersion() const {
return m_info.m_version; return m_info.m_version;
} }
bool Mod::isEnabled() const { bool Mod::isEnabled() const {
return m_enabled; return m_enabled;
} }
bool Mod::isLoaded() const { bool Mod::isLoaded() const {
return m_binaryLoaded; return m_binaryLoaded;
} }
bool Mod::supportsDisabling() const { bool Mod::supportsDisabling() const {
return m_info.m_supportsDisabling; return m_info.m_supportsDisabling;
} }
bool Mod::supportsUnloading() const { bool Mod::supportsUnloading() const {
return m_info.m_supportsUnloading; return m_info.m_supportsUnloading;
} }
bool Mod::wasSuccesfullyLoaded() const { bool Mod::wasSuccesfullyLoaded() const {
return !this->isEnabled() || this->isLoaded(); return !this->isEnabled() || this->isLoaded();
} }
std::vector<Hook*> Mod::getHooks() const { std::vector<Hook*> Mod::getHooks() const {
return m_hooks; return m_hooks;
} }
bool Mod::hasSettings() const { bool Mod::hasSettings() const {
return m_info.m_settings.size(); return m_info.m_settings.size();
} }
decltype(ModInfo::m_settings) Mod::getSettings() const { decltype(ModInfo::m_settings) Mod::getSettings() const {
return m_info.m_settings; return m_info.m_settings;
} }
@ -104,16 +119,19 @@ Result<> Mod::loadData() {
// load its value // load its value
if (!setting->load(value.json())) if (!setting->load(value.json()))
return Err("Unable to load value for setting \"" + key + "\""); return Err("Unable to load value for setting \"" + key + "\"");
} else { }
else {
log::log( log::log(
Severity::Warning, this, Severity::Warning,
this,
"Encountered unknown setting \"{}\" while loading " "Encountered unknown setting \"{}\" while loading "
"settings", "settings",
key key
); );
} }
} }
} catch (std::exception& e) { }
catch (std::exception& e) {
return Err(std::string("Unable to parse settings: ") + e.what()); return Err(std::string("Unable to parse settings: ") + e.what());
} }
} }
@ -124,7 +142,8 @@ Result<> Mod::loadData() {
GEODE_UNWRAP_INTO(auto data, utils::file::readString(savedPath)); GEODE_UNWRAP_INTO(auto data, utils::file::readString(savedPath));
try { try {
m_saved = nlohmann::json::parse(data); m_saved = nlohmann::json::parse(data);
} catch(std::exception& e) { }
catch (std::exception& e) {
return Err(std::string("Unable to parse saved values: ") + e.what()); return Err(std::string("Unable to parse saved values: ") + e.what());
} }
} }
@ -138,20 +157,13 @@ Result<> Mod::saveData() {
// Settings // Settings
auto json = nlohmann::json::object(); auto json = nlohmann::json::object();
for (auto& [key, value] : m_info.m_settings) { for (auto& [key, value] : m_info.m_settings) {
if (!value->save(json[key])) if (!value->save(json[key])) return Err("Unable to save setting \"" + key + "\"");
return Err("Unable to save setting \"" + key + "\"");
} }
GEODE_UNWRAP(utils::file::writeString( GEODE_UNWRAP(utils::file::writeString(m_saveDirPath / "settings.json", json.dump(4)));
m_saveDirPath / "settings.json",
json.dump(4)
));
// Saved values // Saved values
GEODE_UNWRAP(utils::file::writeString( GEODE_UNWRAP(utils::file::writeString(m_saveDirPath / "saved.json", m_saved.dump(4)));
m_saveDirPath / "saved.json",
m_saved.dump(4)
));
return Ok(); return Ok();
} }
@ -180,8 +192,7 @@ Result<> Mod::loadBinary() {
if (!m_binaryLoaded) { if (!m_binaryLoaded) {
GEODE_UNWRAP(this->createTempDir()); GEODE_UNWRAP(this->createTempDir());
if (this->hasUnresolvedDependencies()) if (this->hasUnresolvedDependencies()) return Err("Mod has unresolved dependencies");
return Err("Mod has unresolved dependencies");
GEODE_UNWRAP(this->loadPlatformBinary()); GEODE_UNWRAP(this->loadPlatformBinary());
m_binaryLoaded = true; m_binaryLoaded = true;
@ -206,8 +217,7 @@ Result<> Mod::loadBinary() {
Result<> Mod::unloadBinary() { Result<> Mod::unloadBinary() {
if (m_binaryLoaded) { if (m_binaryLoaded) {
if (!m_info.m_supportsUnloading) if (!m_info.m_supportsUnloading) return Err("Mod does not support unloading");
return Err("Mod does not support unloading");
GEODE_UNWRAP(this->saveData()); GEODE_UNWRAP(this->saveData());
@ -235,8 +245,7 @@ Result<> Mod::unloadBinary() {
} }
Result<> Mod::enable() { Result<> Mod::enable() {
if (!m_binaryLoaded) if (!m_binaryLoaded) return this->loadBinary();
return this->loadBinary();
for (auto const& hook : m_hooks) { for (auto const& hook : m_hooks) {
GEODE_UNWRAP(this->enableHook(hook)); GEODE_UNWRAP(this->enableHook(hook));
@ -255,8 +264,7 @@ Result<> Mod::enable() {
Result<> Mod::disable() { Result<> Mod::disable() {
if (m_enabled) { if (m_enabled) {
if (!m_info.m_supportsDisabling) if (!m_info.m_supportsDisabling) return Err("Mod does not support disabling");
return Err("Mod does not support disabling");
ModStateEvent(this, ModEventType::Disabled).post(); ModStateEvent(this, ModEventType::Disabled).post();
@ -278,8 +286,7 @@ Result<> Mod::uninstall() {
if (m_info.m_supportsDisabling) { if (m_info.m_supportsDisabling) {
GEODE_UNWRAP(this->disable()); GEODE_UNWRAP(this->disable());
if (m_info.m_supportsUnloading) if (m_info.m_supportsUnloading) GEODE_UNWRAP(this->unloadBinary());
GEODE_UNWRAP(this->unloadBinary());
} }
if (!ghc::filesystem::remove(m_info.m_path)) { if (!ghc::filesystem::remove(m_info.m_path)) {
@ -308,15 +315,15 @@ bool Dependency::isUnresolved() const {
bool Mod::updateDependencyStates() { bool Mod::updateDependencyStates() {
bool hasUnresolved = false; bool hasUnresolved = false;
for (auto& dep : m_info.m_dependencies) { for (auto& dep : m_info.m_dependencies) {
if (!dep.m_mod) if (!dep.m_mod) dep.m_mod = Loader::get()->getLoadedMod(dep.m_id);
dep.m_mod = Loader::get()->getLoadedMod(dep.m_id);
if (dep.m_mod) { if (dep.m_mod) {
dep.m_mod->updateDependencyStates(); dep.m_mod->updateDependencyStates();
if (dep.m_mod->hasUnresolvedDependencies()) { if (dep.m_mod->hasUnresolvedDependencies()) {
dep.m_state = ModResolveState::Unresolved; dep.m_state = ModResolveState::Unresolved;
} else { }
else {
if (!dep.m_mod->m_resolved) { if (!dep.m_mod->m_resolved) {
dep.m_mod->m_resolved = true; dep.m_mod->m_resolved = true;
dep.m_state = ModResolveState::Resolved; dep.m_state = ModResolveState::Resolved;
@ -325,15 +332,18 @@ bool Mod::updateDependencyStates() {
dep.m_state = ModResolveState::Unloaded; dep.m_state = ModResolveState::Unloaded;
log::log(Severity::Error, dep.m_mod, "{}", r.unwrapErr()); log::log(Severity::Error, dep.m_mod, "{}", r.unwrapErr());
} }
} else { }
else {
if (dep.m_mod->isEnabled()) { if (dep.m_mod->isEnabled()) {
dep.m_state = ModResolveState::Loaded; dep.m_state = ModResolveState::Loaded;
} else { }
else {
dep.m_state = ModResolveState::Disabled; dep.m_state = ModResolveState::Disabled;
} }
} }
} }
} else { }
else {
dep.m_state = ModResolveState::Unloaded; dep.m_state = ModResolveState::Unloaded;
} }
if (dep.isUnresolved()) { if (dep.isUnresolved()) {
@ -352,7 +362,8 @@ bool Mod::updateDependencyStates() {
if (!r) { if (!r) {
log::error("{} Error loading: {}", this, r.unwrapErr()); log::error("{} Error loading: {}", this, r.unwrapErr());
} }
} else { }
else {
log::debug("Resolved {}, however not loading it as it is disabled", m_info.m_id); log::debug("Resolved {}, however not loading it as it is disabled", m_info.m_id);
} }
} }
@ -361,8 +372,7 @@ bool Mod::updateDependencyStates() {
bool Mod::hasUnresolvedDependencies() const { bool Mod::hasUnresolvedDependencies() const {
for (auto const& dep : m_info.m_dependencies) { for (auto const& dep : m_info.m_dependencies) {
if (dep.isUnresolved()) if (dep.isUnresolved()) return true;
return true;
} }
return false; return false;
} }
@ -370,8 +380,7 @@ bool Mod::hasUnresolvedDependencies() const {
std::vector<Dependency> Mod::getUnresolvedDependencies() { std::vector<Dependency> Mod::getUnresolvedDependencies() {
std::vector<Dependency> unresolved; std::vector<Dependency> unresolved;
for (auto const& dep : m_info.m_dependencies) { for (auto const& dep : m_info.m_dependencies) {
if (dep.isUnresolved()) if (dep.isUnresolved()) unresolved.push_back(dep);
unresolved.push_back(dep);
} }
return unresolved; return unresolved;
} }
@ -386,8 +395,7 @@ bool Mod::depends(std::string const& id) const {
Result<> Mod::enableHook(Hook* hook) { Result<> Mod::enableHook(Hook* hook) {
auto res = hook->enable(); auto res = hook->enable();
if (res) if (res) m_hooks.push_back(hook);
m_hooks.push_back(hook);
return res; return res;
} }
@ -403,11 +411,12 @@ Result<Hook*> Mod::addHook(Hook* hook) {
delete hook; delete hook;
return Err("Can't create hook"); return Err("Can't create hook");
} }
} else { }
else {
InternalLoader::get()->addInternalHook(hook, this); InternalLoader::get()->addInternalHook(hook, this);
} }
return Ok<Hook*>(hook); return Ok(hook);
} }
Result<> Mod::removeHook(Hook* hook) { Result<> Mod::removeHook(Hook* hook) {
@ -440,7 +449,7 @@ Result<Patch*> Mod::patch(void* address, byte_array data) {
return Err("Unable to enable patch at " + std::to_string(p->getAddress())); return Err("Unable to enable patch at " + std::to_string(p->getAddress()));
} }
m_patches.push_back(p); m_patches.push_back(p);
return Ok<Patch*>(p); return Ok(p);
} }
Result<> Mod::unpatch(Patch* patch) { Result<> Mod::unpatch(Patch* patch) {
@ -473,8 +482,7 @@ Result<> Mod::createTempDir() {
GEODE_UNWRAP_INTO(auto unzip, file::Unzip::create(m_info.m_path)); GEODE_UNWRAP_INTO(auto unzip, file::Unzip::create(m_info.m_path));
if (!unzip.hasEntry(m_info.m_binaryName)) { if (!unzip.hasEntry(m_info.m_binaryName)) {
return Err(fmt::format( return Err(fmt::format(
"Unable to find platform binary under the name \"{}\"", "Unable to find platform binary under the name \"{}\"", m_info.m_binaryName
m_info.m_binaryName
)); ));
} }
GEODE_UNWRAP(unzip.extractAllTo(tempPath)); GEODE_UNWRAP(unzip.extractAllTo(tempPath));
@ -495,10 +503,9 @@ ghc::filesystem::path Mod::getConfigDir(bool create) const {
return dir; return dir;
} }
const char* Mod::expandSpriteName(const char* name) { char const* Mod::expandSpriteName(char const* name) {
static std::unordered_map<std::string, const char*> expanded = {}; static std::unordered_map<std::string, char const*> expanded = {};
if (expanded.count(name)) if (expanded.count(name)) return expanded[name];
return expanded[name];
auto exp = new char[strlen(name) + 2 + m_info.m_id.size()]; auto exp = new char[strlen(name) + 2 + m_info.m_id.size()];
auto exps = m_info.m_id + "/" + name; auto exps = m_info.m_id + "/" + name;

View file

@ -19,7 +19,4 @@ ListenerResult ModStateFilter::handle(std::function<Callback> fn, ModStateEvent*
return ListenerResult::Propagate; return ListenerResult::Propagate;
} }
ModStateFilter::ModStateFilter( ModStateFilter::ModStateFilter(Mod* mod, ModEventType type) : m_mod(mod), m_type(type) {}
Mod* mod,
ModEventType type
) : m_mod(mod), m_type(type) {}

View file

@ -123,7 +123,7 @@ Result<ModInfo> ModInfo::create(ModJson const& json) {
if (schema < Loader::minModVersion()) { if (schema < Loader::minModVersion()) {
return Err( return Err(
"[mod.json] is built for an older version (" + schema.toString() + "[mod.json] is built for an older version (" + schema.toString() +
") of Geode (current: " + Loader::minModVersion().toString() + ") of Geode (current: " + Loader::getVersion().toString() +
"). Please update the mod to the latest version, " "). Please update the mod to the latest version, "
"and if the problem persists, contact the developer " "and if the problem persists, contact the developer "
"to update it." "to update it."
@ -132,7 +132,7 @@ Result<ModInfo> ModInfo::create(ModJson const& json) {
if (schema > Loader::maxModVersion()) { if (schema > Loader::maxModVersion()) {
return Err( return Err(
"[mod.json] is built for a newer version (" + schema.toString() + "[mod.json] is built for a newer version (" + schema.toString() +
") of Geode (current: " + Loader::maxModVersion().toString() + ") of Geode (current: " + Loader::getVersion().toString() +
"). You need to update Geode in order to use " "). You need to update Geode in order to use "
"this mod." "this mod."
); );

View file

@ -1,11 +1,11 @@
#include "../core/Core.hpp" #include "../core/Core.hpp"
#include <Geode/loader/IPC.hpp>
#include <Geode/loader/Loader.hpp> #include <Geode/loader/Loader.hpp>
#include <Geode/loader/Log.hpp> #include <Geode/loader/Log.hpp>
#include <Geode/loader/Mod.hpp> #include <Geode/loader/Mod.hpp>
#include <Geode/loader/SettingEvent.hpp>
#include <Geode/loader/Setting.hpp> #include <Geode/loader/Setting.hpp>
#include <Geode/loader/IPC.hpp> #include <Geode/loader/SettingEvent.hpp>
#include <InternalLoader.hpp> #include <InternalLoader.hpp>
#include <InternalMod.hpp> #include <InternalMod.hpp>
#include <array> #include <array>
@ -102,27 +102,25 @@ BOOL WINAPI DllMain(HINSTANCE lib, DWORD reason, LPVOID) {
#define $_ GEODE_CONCAT(unnamedVar_, __LINE__) #define $_ GEODE_CONCAT(unnamedVar_, __LINE__)
static auto $_ = listenForSettingChanges<BoolSetting>( static auto $_ =
"show-platform-console", listenForSettingChanges<BoolSetting>("show-platform-console", [](BoolSetting* setting) {
[](BoolSetting* setting) {
if (setting->getValue()) { if (setting->getValue()) {
Loader::get()->openPlatformConsole(); Loader::get()->openPlatformConsole();
} }
else { else {
Loader::get()->closePlatfromConsole(); Loader::get()->closePlatfromConsole();
} }
} });
);
static auto $_ = listenForIPC("ipc-test", +[](IPCEvent* event) -> nlohmann::json { static auto $_ = listenForIPC("ipc-test", [](IPCEvent* event) -> nlohmann::json {
return "Hello from Geode!"; return "Hello from Geode!";
}); });
static auto $_ = listenForIPC("loader-info", +[](IPCEvent* event) -> nlohmann::json { static auto $_ = listenForIPC("loader-info", [](IPCEvent* event) -> nlohmann::json {
return Loader::get()->getInternalMod()->getModInfo(); return Loader::get()->getInternalMod()->getModInfo();
}); });
static auto $_ = listenForIPC("list-mods", +[](IPCEvent* event) -> nlohmann::json { static auto $_ = listenForIPC("list-mods", [](IPCEvent* event) -> nlohmann::json {
std::vector<nlohmann::json> res; std::vector<nlohmann::json> res;
auto args = event->getMessageData(); auto args = event->getMessageData();
@ -133,18 +131,14 @@ static auto $_ = listenForIPC("list-mods", +[](IPCEvent* event) -> nlohmann::jso
auto dontIncludeLoader = root.has("dont-include-loader").template get<bool>(); auto dontIncludeLoader = root.has("dont-include-loader").template get<bool>();
if (!dontIncludeLoader) { if (!dontIncludeLoader) {
res.push_back(includeRunTimeInfo ? res.push_back(
Loader::get()->getInternalMod()->getRuntimeInfo() : includeRunTimeInfo ? Loader::get()->getInternalMod()->getRuntimeInfo() :
Loader::get()->getInternalMod()->getModInfo().toJSON() Loader::get()->getInternalMod()->getModInfo().toJSON()
); );
} }
for (auto& mod : Loader::get()->getAllMods()) { for (auto& mod : Loader::get()->getAllMods()) {
res.push_back( res.push_back(includeRunTimeInfo ? mod->getRuntimeInfo() : mod->getModInfo().toJSON());
includeRunTimeInfo ?
mod->getRuntimeInfo() :
mod->getModInfo().toJSON()
);
} }
return res; return res;

View file

@ -5,10 +5,6 @@
#include <cocos2d.h> #include <cocos2d.h>
using namespace cocos2d; using namespace cocos2d;
void CCFileUtils::removeAllPaths() {
m_searchPathArray.clear();
}
CCObject* CCObject::copy() CCObject* CCObject::copy()
{ {
return copyWithZone(0); return copyWithZone(0);

View file

@ -1,8 +1,8 @@
#include <InternalLoader.hpp>
#include <Geode/loader/Log.hpp>
#include <iostream>
#include <InternalMod.hpp>
#include <Geode/loader/IPC.hpp> #include <Geode/loader/IPC.hpp>
#include <Geode/loader/Log.hpp>
#include <InternalLoader.hpp>
#include <InternalMod.hpp>
#include <iostream>
#ifdef GEODE_IS_MACOS #ifdef GEODE_IS_MACOS
@ -29,46 +29,37 @@ void InternalLoader::closePlatformConsole() {
m_platformConsoleOpen = false; m_platformConsoleOpen = false;
} }
CFDataRef msgPortCallback( CFDataRef msgPortCallback(CFMessagePortRef port, SInt32 messageID, CFDataRef data, void* info) {
CFMessagePortRef port, if (!CFDataGetLength(data)) return NULL;
SInt32 messageID,
CFDataRef data,
void* info
) {
if(!CFDataGetLength(data))
return NULL;
std::string cdata( std::string cdata(reinterpret_cast<char const*>(CFDataGetBytePtr(data)), CFDataGetLength(data));
reinterpret_cast<char const*>(CFDataGetBytePtr(data)),
CFDataGetLength(data)
);
std::string reply = InternalLoader::processRawIPC(port, cdata); std::string reply = InternalLoader::processRawIPC(port, cdata);
return CFDataCreate(NULL, (const UInt8*)reply.data(), reply.size()); return CFDataCreate(NULL, (UInt8 const*)reply.data(), reply.size());
} }
void InternalLoader::setupIPC() { void InternalLoader::setupIPC() {
std::thread([]() { std::thread([]() {
CFStringRef portName = CFStringCreateWithCString(NULL, IPC_PORT_NAME, kCFStringEncodingUTF8); CFStringRef portName = CFStringCreateWithCString(NULL, IPC_PORT_NAME, kCFStringEncodingUTF8);
CFMessagePortRef localPort = CFMessagePortCreateLocal( CFMessagePortRef localPort =
NULL, CFMessagePortCreateLocal(NULL, portName, msgPortCallback, NULL, NULL);
portName, if (localPort == NULL) {
msgPortCallback, log::warn("Unable to create port, quitting IPC");
NULL, return;
NULL }
);
CFRunLoopSourceRef runLoopSource = CFMessagePortCreateRunLoopSource(NULL, localPort, 0); CFRunLoopSourceRef runLoopSource = CFMessagePortCreateRunLoopSource(NULL, localPort, 0);
CFRunLoopAddSource( if (runLoopSource == NULL) {
CFRunLoopGetCurrent(), log::warn("Unable to create loop source, quitting IPC");
runLoopSource, return;
kCFRunLoopCommonModes }
);
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes);
CFRunLoopRun(); CFRunLoopRun();
CFRelease(localPort); CFRelease(localPort);
}).detach(); }).detach();
log::log(Severity::Warning, InternalMod::get(), "IPC is not supported on this platform"); log::debug("IPC set up");
} }
#endif #endif

View file

@ -1,8 +1,8 @@
#include <InternalLoader.hpp>
#include <Geode/loader/IPC.hpp> #include <Geode/loader/IPC.hpp>
#include <Geode/loader/Log.hpp> #include <Geode/loader/Log.hpp>
#include <iostream> #include <InternalLoader.hpp>
#include <InternalMod.hpp> #include <InternalMod.hpp>
#include <iostream>
USE_GEODE_NAMESPACE(); USE_GEODE_NAMESPACE();
@ -89,14 +89,15 @@ void InternalLoader::setupIPC() {
if (ConnectNamedPipe(pipe, nullptr)) { if (ConnectNamedPipe(pipe, nullptr)) {
// log::debug("Got connection, creating thread"); // log::debug("Got connection, creating thread");
std::thread(&ipcPipeThread, pipe).detach(); std::thread(&ipcPipeThread, pipe).detach();
} else { }
else {
// log::debug("No connection, cleaning pipe"); // log::debug("No connection, cleaning pipe");
CloseHandle(pipe); CloseHandle(pipe);
} }
} }
}).detach(); }).detach();
log::log(Severity::Debug, InternalMod::get(), "IPC set up"); log::debug("IPC set up");
} }
#endif #endif

View file

@ -1,6 +1,6 @@
#include <Geode/binding/LoadingCircle.hpp> #include <Geode/binding/LoadingCircle.hpp>
#include <Geode/ui/Notification.hpp>
#include <Geode/loader/Mod.hpp> #include <Geode/loader/Mod.hpp>
#include <Geode/ui/Notification.hpp>
USE_GEODE_NAMESPACE(); USE_GEODE_NAMESPACE();
@ -10,8 +10,7 @@ constexpr auto NOTIFICATION_FADEOUT = 1.f;
Ref<CCArray> Notification::s_queue = CCArray::create(); Ref<CCArray> Notification::s_queue = CCArray::create();
bool Notification::init(std::string const& text, CCSprite* icon, float time) { bool Notification::init(std::string const& text, CCSprite* icon, float time) {
if (!CCNodeRGBA::init()) if (!CCNodeRGBA::init()) return false;
return false;
m_time = time; m_time = time;
@ -48,7 +47,8 @@ void Notification::updateLayout() {
if (m_icon) { if (m_icon) {
m_icon->setPosition({ size.height / 2, size.height / 2 }); m_icon->setPosition({ size.height / 2, size.height / 2 });
m_label->setPosition(size / 2 + CCSize { spaceForIcon / 2, .0f }); m_label->setPosition(size / 2 + CCSize { spaceForIcon / 2, .0f });
} else { }
else {
m_label->setPosition(size / 2); m_label->setPosition(size / 2);
} }
} }
@ -73,9 +73,7 @@ CCSprite* Notification::createIcon(NotificationIcon icon) {
case NotificationIcon::Loading: { case NotificationIcon::Loading: {
auto icon = CCSprite::create("loadingCircle.png"); auto icon = CCSprite::create("loadingCircle.png");
icon->runAction(CCRepeatForever::create( icon->runAction(CCRepeatForever::create(CCRotateBy::create(1.f, 360.f)));
CCRotateBy::create(1.f, 360.f)
));
icon->setBlendFunc({ GL_ONE, GL_ONE }); icon->setBlendFunc({ GL_ONE, GL_ONE });
return icon; return icon;
} break; } break;
@ -94,11 +92,7 @@ CCSprite* Notification::createIcon(NotificationIcon icon) {
} }
} }
Notification* Notification::create( Notification* Notification::create(std::string const& text, NotificationIcon icon, float time) {
std::string const& text,
NotificationIcon icon,
float time
) {
return Notification::create(text, createIcon(icon), time); return Notification::create(text, createIcon(icon), time);
} }
@ -125,7 +119,8 @@ void Notification::setIcon(cocos2d::CCSprite* icon) {
if (m_icon) { if (m_icon) {
m_icon->removeFromParent(); m_icon->removeFromParent();
} }
if (m_icon = icon) { m_icon = icon;
if (icon) {
m_bg->addChild(icon); m_bg->addChild(icon);
} }
this->updateLayout(); this->updateLayout();
@ -171,8 +166,7 @@ void Notification::show() {
CCCallFunc::create(this, callfunc_selector(Notification::animateIn)), CCCallFunc::create(this, callfunc_selector(Notification::animateIn)),
// wait for fade-in to finish // wait for fade-in to finish
CCDelayTime::create(NOTIFICATION_FADEIN), CCDelayTime::create(NOTIFICATION_FADEIN),
CCCallFunc::create(this, callfunc_selector(Notification::wait)), CCCallFunc::create(this, callfunc_selector(Notification::wait)), nullptr
nullptr
)); ));
} }
@ -181,8 +175,7 @@ void Notification::wait() {
if (m_time) { if (m_time) {
this->runAction(CCSequence::create( this->runAction(CCSequence::create(
CCDelayTime::create(m_time), CCDelayTime::create(m_time),
CCCallFunc::create(this, callfunc_selector(Notification::hide)), CCCallFunc::create(this, callfunc_selector(Notification::hide)), nullptr
nullptr
)); ));
} }
} }
@ -193,8 +186,6 @@ void Notification::hide() {
CCCallFunc::create(this, callfunc_selector(Notification::animateOut)), CCCallFunc::create(this, callfunc_selector(Notification::animateOut)),
// wait for fade-out to finish // wait for fade-out to finish
CCDelayTime::create(NOTIFICATION_FADEOUT), CCDelayTime::create(NOTIFICATION_FADEOUT),
CCCallFunc::create(this, callfunc_selector(Notification::showNextNotification)), CCCallFunc::create(this, callfunc_selector(Notification::showNextNotification)), nullptr
nullptr
)); ));
} }

View file

@ -205,14 +205,12 @@ JsonMaybeValue<Json> JsonMaybeValue<Json>::at(size_t i) {
return *this; return *this;
} }
return JsonMaybeValue<Json>( return JsonMaybeValue<Json>(
self().m_checker, self().m_json.at(i), self().m_hierarchy + "." + std::to_string(i), self().m_checker, self().m_json.at(i), self().m_hierarchy + "." + std::to_string(i), self().m_hasValue
self().m_hasValue
); );
} }
template <class Json> template <class Json>
typename JsonMaybeValue<Json>::template Iterator<JsonMaybeValue<Json>> JsonMaybeValue< typename JsonMaybeValue<Json>::template Iterator<JsonMaybeValue<Json>> JsonMaybeValue<Json>::iterate() {
Json>::iterate() {
this->as<value_t::array>(); this->as<value_t::array>();
Iterator<JsonMaybeValue<Json>> iter; Iterator<JsonMaybeValue<Json>> iter;
if (this->isError()) return iter; if (this->isError()) return iter;
@ -226,8 +224,8 @@ typename JsonMaybeValue<Json>::template Iterator<JsonMaybeValue<Json>> JsonMaybe
} }
template <class Json> template <class Json>
typename JsonMaybeValue<Json>::template Iterator<std::pair<std::string, JsonMaybeValue<Json>>> typename JsonMaybeValue<Json>::template Iterator<std::pair<std::string, JsonMaybeValue<Json>>> JsonMaybeValue<
JsonMaybeValue<Json>::items() { Json>::items() {
this->as<value_t::object>(); this->as<value_t::object>();
Iterator<std::pair<std::string, JsonMaybeValue<Json>>> iter; Iterator<std::pair<std::string, JsonMaybeValue<Json>>> iter;
if (this->isError()) return iter; if (this->isError()) return iter;
@ -235,9 +233,7 @@ JsonMaybeValue<Json>::items() {
for (auto& [k, v] : self().m_json.items()) { for (auto& [k, v] : self().m_json.items()) {
iter.m_values.emplace_back( iter.m_values.emplace_back(
k, k,
JsonMaybeValue<Json>( JsonMaybeValue<Json>(self().m_checker, v, self().m_hierarchy + "." + k, self().m_hasValue)
self().m_checker, v, self().m_hierarchy + "." + k, self().m_hasValue
)
); );
} }

View file

@ -14,8 +14,7 @@
macro(GEODE_CONCAT(begin, 7)), macro(GEODE_CONCAT(begin, 8)), \ macro(GEODE_CONCAT(begin, 7)), macro(GEODE_CONCAT(begin, 8)), \
macro(GEODE_CONCAT(begin, 9)), macro(GEODE_CONCAT(begin, a)), \ macro(GEODE_CONCAT(begin, 9)), macro(GEODE_CONCAT(begin, a)), \
macro(GEODE_CONCAT(begin, b)), macro(GEODE_CONCAT(begin, c)), \ macro(GEODE_CONCAT(begin, b)), macro(GEODE_CONCAT(begin, c)), \
macro(GEODE_CONCAT(begin, d)), macro(GEODE_CONCAT(begin, e)), \ macro(GEODE_CONCAT(begin, d)), macro(GEODE_CONCAT(begin, e)), macro(GEODE_CONCAT(begin, f))
macro(GEODE_CONCAT(begin, f))
#define GEODE_ADDRESSER_NEST2(macro, begin) \ #define GEODE_ADDRESSER_NEST2(macro, begin) \
GEODE_ADDRESSER_NEST1(macro, GEODE_CONCAT(begin, 0)), \ GEODE_ADDRESSER_NEST1(macro, GEODE_CONCAT(begin, 0)), \

View file

@ -1,5 +1,5 @@
#include <Geode/utils/cocos.hpp>
#include <Geode/modify/LoadingLayer.hpp> #include <Geode/modify/LoadingLayer.hpp>
#include <Geode/utils/cocos.hpp>
USE_GEODE_NAMESPACE(); USE_GEODE_NAMESPACE();
@ -20,9 +20,7 @@ void cocos2d::from_json(nlohmann::json const& json, ccColor3B& color) {
json.at(2).get_to(color.b); json.at(2).get_to(color.b);
} }
else { else {
throw nlohmann::json::type_error::create( throw nlohmann::json::type_error::create(0, "Expected color array to have 3 items", json);
0, "Expected color array to have 3 items", json
);
} }
} }
// object // object
@ -75,9 +73,7 @@ void cocos2d::from_json(nlohmann::json const& json, ccColor4B& color) {
json.at(3).get_to(color.a); json.at(3).get_to(color.a);
} }
else { else {
throw nlohmann::json::type_error::create( throw nlohmann::json::type_error::create(0, "Expected color array to have 4 items", json);
0, "Expected color array to have 4 items", json
);
} }
} }
// object // object
@ -288,9 +284,7 @@ CCRect geode::cocos::calculateChildCoverage(CCNode* parent) {
return calculateNodeCoverage(parent->getChildren()); return calculateNodeCoverage(parent->getChildren());
} }
void geode::cocos::limitNodeSize( void geode::cocos::limitNodeSize(cocos2d::CCNode* spr, cocos2d::CCSize const& size, float def, float min) {
cocos2d::CCNode* spr, cocos2d::CCSize const& size, float def, float min
) {
spr->setScale(1.f); spr->setScale(1.f);
auto [cwidth, cheight] = spr->getContentSize(); auto [cwidth, cheight] = spr->getContentSize();
@ -346,7 +340,7 @@ void geode::cocos::reloadTextures(CreateLayerFunc returnTo) {
GameManager::get()->reloadAll(false, false, true); GameManager::get()->reloadAll(false, false, true);
} }
class $modify(LoadingLayer) { struct LoadingFinished : Modify<LoadingFinished, LoadingLayer> {
void loadAssets() { void loadAssets() {
// loadFinished is inlined on Macchew OS :sob: // loadFinished is inlined on Macchew OS :sob:

View file

@ -1,11 +1,11 @@
#include <Geode/utils/file.hpp>
#include <Geode/utils/string.hpp>
#include <Geode/utils/map.hpp>
#include <Geode/loader/Log.hpp>
#include <fstream>
#include <../support/zip_support/ZipUtils.h> #include <../support/zip_support/ZipUtils.h>
#include <../support/zip_support/ioapi.h> #include <../support/zip_support/ioapi.h>
#include <../support/zip_support/unzip.h> #include <../support/zip_support/unzip.h>
#include <Geode/loader/Log.hpp>
#include <Geode/utils/file.hpp>
#include <Geode/utils/map.hpp>
#include <Geode/utils/string.hpp>
#include <fstream>
USE_GEODE_NAMESPACE(); USE_GEODE_NAMESPACE();
using namespace geode::utils::file; using namespace geode::utils::file;
@ -143,9 +143,7 @@ public:
unz_file_info64 fileInfo; unz_file_info64 fileInfo;
// Read first file // Read first file
if (unzGoToFirstFile64( if (unzGoToFirstFile64(m_zip, &fileInfo, fileName, sizeof(fileName) - 1)) {
m_zip, &fileInfo, fileName, sizeof(fileName) - 1
)) {
return false; return false;
} }
// Loop over all files // Loop over all files
@ -154,17 +152,16 @@ public:
unz_file_pos pos; unz_file_pos pos;
if (unzGetFilePos(m_zip, &pos) == UNZ_OK) { if (unzGetFilePos(m_zip, &pos) == UNZ_OK) {
m_entries.insert({ m_entries.insert({
fileName, ZipEntry { fileName,
ZipEntry {
.m_pos = pos, .m_pos = pos,
.m_compressedSize = fileInfo.compressed_size, .m_compressedSize = fileInfo.compressed_size,
.m_uncompressedSize = fileInfo.uncompressed_size, .m_uncompressedSize = fileInfo.uncompressed_size,
} },
}); });
} }
// Read next file, or break on error // Read next file, or break on error
if (unzGoToNextFile64( if (unzGoToNextFile64(m_zip, &fileInfo, fileName, sizeof(fileName) - 1) != UNZ_OK) {
m_zip, &fileInfo, fileName, sizeof(fileName) - 1
) != UNZ_OK) {
break; break;
} }
} }
@ -204,6 +201,7 @@ public:
} }
UnzipImpl(unzFile zip, Path const& path) : m_zip(zip), m_zipPath(path) {} UnzipImpl(unzFile zip, Path const& path) : m_zip(zip), m_zipPath(path) {}
~UnzipImpl() { ~UnzipImpl() {
unzClose(m_zip); unzClose(m_zip);
} }

View file

@ -91,9 +91,7 @@ std::wstring utils::string::toUpper(std::wstring const& str) {
return utils::string::toUpperIP(ret); return utils::string::toUpperIP(ret);
} }
std::string& utils::string::replaceIP( std::string& utils::string::replaceIP(std::string& str, std::string const& orig, std::string const& repl) {
std::string& str, std::string const& orig, std::string const& repl
) {
std::string::size_type n = 0; std::string::size_type n = 0;
while ((n = str.find(orig, n)) != std::string::npos) { while ((n = str.find(orig, n)) != std::string::npos) {
str.replace(n, orig.size(), repl); str.replace(n, orig.size(), repl);
@ -248,7 +246,8 @@ std::wstring& utils::string::trimLeftIP(std::wstring& str) {
std::string& utils::string::trimRightIP(std::string& str) { std::string& utils::string::trimRightIP(std::string& str) {
str.erase( str.erase(
std::find_if( std::find_if(
str.rbegin(), str.rend(), str.rbegin(),
str.rend(),
[](auto ch) { [](auto ch) {
return !std::isspace(ch); return !std::isspace(ch);
} }
@ -261,7 +260,8 @@ std::string& utils::string::trimRightIP(std::string& str) {
std::wstring& utils::string::trimRightIP(std::wstring& str) { std::wstring& utils::string::trimRightIP(std::wstring& str) {
str.erase( str.erase(
std::find_if( std::find_if(
str.rbegin(), str.rend(), str.rbegin(),
str.rend(),
[](auto ch) { [](auto ch) {
return !std::isspace(ch); return !std::isspace(ch);
} }

View file

@ -193,7 +193,8 @@ SentAsyncWebRequest::SentAsyncWebRequest(AsyncWebRequest const& req, std::string
} data{this, file.get()}; } data{this, file.get()};
curl_easy_setopt( curl_easy_setopt(
curl, CURLOPT_PROGRESSFUNCTION, curl,
CURLOPT_PROGRESSFUNCTION,
+[](void* ptr, double total, double now, double, double) -> int { +[](void* ptr, double total, double now, double, double) -> int {
auto data = static_cast<ProgressData*>(ptr); auto data = static_cast<ProgressData*>(ptr);
while (data->self->m_paused) {} while (data->self->m_paused) {}