added clang-format

This commit is contained in:
altalk23 2022-10-30 21:24:06 +03:00
parent a1c9063767
commit 94d45ccf21
10 changed files with 963 additions and 703 deletions

140
.clang-format Normal file
View file

@ -0,0 +1,140 @@
---
Language: Cpp
IndentWidth: 4
AlignAfterOpenBracket: BlockIndent
AlignEscapedNewlines: Left
AlignOperands: DontAlign
AlignTrailingComments: false
AllowAllArgumentsOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: Empty
AllowShortFunctionsOnASingleLine: Empty
AllowShortLambdasOnASingleLine: Empty
AllowShortCaseLabelsOnASingleLine: false
AllowShortEnumsOnASingleLine: false
AllowShortIfStatementsOnASingleLine: AllIfsAndElse
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: Never
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: true
BeforeElse: true
BeforeLambdaBody: false
BeforeWhile: false
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyRecord: false
SplitEmptyNamespace: false
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Custom
BreakBeforeConceptDeclarations: true
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: AfterColon
BreakInheritanceList: AfterColon
BreakStringLiterals: true
ColumnLimit: 100
CompactNamespaces: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: false
DeriveLineEnding: false
UseCRLF: false
UseTab: Never
PointerAlignment: Left
ReferenceAlignment: Pointer
EmptyLineBeforeAccessModifier: Always
FixNamespaceComments: false
IncludeBlocks: Regroup
IncludeCategories:
- Regex: '^".*"'
Priority: 1
- Regex: '^<.*>'
Priority: 2
IndentAccessModifiers: false
AccessModifierOffset: -4
IndentCaseBlocks: false
IndentCaseLabels: false
IndentExternBlock: Indent
IndentGotoLabels: true
IndentPPDirectives: BeforeHash
IndentWrappedFunctionNames: true
# InsertBraces: true
InsertTrailingCommas: None
KeepEmptyLinesAtTheStartOfBlocks: false
MaxEmptyLinesToKeep: 1
LambdaBodyIndentation: Signature
NamespaceIndentation: All
PPIndentWidth: -1
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PenaltyIndentedWhitespace: 0
QualifierAlignment: Right
ReflowComments: true
SeparateDefinitionBlocks: Always
SortIncludes: CaseSensitive
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceAroundPointerQualifiers: Default
SpaceBeforeAssignmentOperators: true
SpaceBeforeCaseColon: false
SpaceBeforeCpp11BracedList: true
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceBeforeSquareBrackets: false
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: Never
SpacesInCStyleCastParentheses: false
SpacesInConditionalStatement: false
SpacesInLineCommentPrefix:
Minimum: 1
Maximum: -1
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: c++20

View file

@ -952,6 +952,7 @@ class cocos2d::extension::CCScale9Sprite {
CCScale9Sprite() = mac 0x211330; CCScale9Sprite() = mac 0x211330;
static cocos2d::extension::CCScale9Sprite* create(char const*) = mac 0x2130d0; static cocos2d::extension::CCScale9Sprite* create(char const*) = mac 0x2130d0;
static cocos2d::extension::CCScale9Sprite* create(char const*, cocos2d::CCRect) = mac 0x212ef0; static cocos2d::extension::CCScale9Sprite* create(char const*, cocos2d::CCRect) = mac 0x212ef0;
static cocos2d::extension::CCScale9Sprite* create(char const*, cocos2d::CCRect, cocos2d::CCRect) = mac 0x212dd0;
static cocos2d::extension::CCScale9Sprite* createWithSpriteFrameName(char const*, cocos2d::CCRect) = mac 0x213380; static cocos2d::extension::CCScale9Sprite* createWithSpriteFrameName(char const*, cocos2d::CCRect) = mac 0x213380;
static cocos2d::extension::CCScale9Sprite* createWithSpriteFrameName(char const*) = mac 0x213460; static cocos2d::extension::CCScale9Sprite* createWithSpriteFrameName(char const*) = mac 0x213460;
virtual ~CCScale9Sprite() = mac 0x211590; virtual ~CCScale9Sprite() = mac 0x211590;

View file

@ -1,3 +1,22 @@
// geode additions to make stl containers easier
class GDString {
void winDtor() = win 0xf6e0;
char const* winCStr() = win 0xf710;
GDString& winAssign(GDString const&, size_t, size_t) = win 0xf720;
GDString& winAssign(char const*) = win 0xf680;
GDString& winAssign(char const*, size_t) = win 0xf840;
static uintptr_t macEmptyContainer() {
return geode::base::get() + 0x6030d0;
}
void macCtor(char const*) = mac 0x489fc0;
void macCtor(GDString const&) = mac 0x489fcc;
GDString& macAssign(char const*) = mac 0x489f96;
GDString& macAssign(GDString const&) = mac 0x489f9c;
void macDestroy() = mac 0x489f78;
}
class AchievementBar : cocos2d::CCNodeRGBA { class AchievementBar : cocos2d::CCNodeRGBA {
static AchievementBar* create(const char* title, const char* desc, const char* icon, bool quest) = mac 0x379f80, win 0x3b120, ios 0x1a4784; static AchievementBar* create(const char* title, const char* desc, const char* icon, bool quest) = mac 0x379f80, win 0x3b120, ios 0x1a4784;
@ -67,7 +86,9 @@ class AppDelegate : cocos2d::CCApplication {
virtual void applicationWillResignActive() = mac 0x3aab50, win 0x3cf20; virtual void applicationWillResignActive() = mac 0x3aab50, win 0x3cf20;
virtual void trySaveGame() = mac 0x3aaf10, win 0x3d5e0, ios 0x1a28f0; virtual void trySaveGame() = mac 0x3aaf10, win 0x3d5e0, ios 0x1a28f0;
virtual void willSwitchToScene(cocos2d::CCScene*) = mac 0x3aaf40, win 0x3d690; virtual void willSwitchToScene(cocos2d::CCScene*) = mac 0x3aaf40, win 0x3d690;
static AppDelegate* get() = mac 0x3aab10; static AppDelegate* get() {
return static_cast<AppDelegate*>(cocos2d::CCApplication::sharedApplication());
}
bool musicTest() = win 0x3d580; bool musicTest() = win 0x3d580;
void pauseGame() = mac 0x3aab60, win 0x3d3e0; void pauseGame() = mac 0x3aab60, win 0x3d3e0;
void resumeSound() = win 0x3d4d0; void resumeSound() = win 0x3d4d0;
@ -814,7 +835,7 @@ class CreatorLayer : cocos2d::CCLayer {
void onBack(cocos2d::CCObject*) = win 0x4fae0; void onBack(cocos2d::CCObject*) = win 0x4fae0;
void onChallenge(cocos2d::CCObject*) = win 0x4f1b0; void onChallenge(cocos2d::CCObject*) = win 0x4f1b0;
void onLeaderboards(cocos2d::CCObject*) = win 0x4ed20; void onLeaderboards(cocos2d::CCObject*) = win 0x4ed20;
void onMyLevels(cocos2d::CCObject*) = mac 0x142b70; void onMyLevels(cocos2d::CCObject*) = mac 0x142b70, win 0x4eaa0;
void onSavedLevels(cocos2d::CCObject*) = mac 0x142860; void onSavedLevels(cocos2d::CCObject*) = mac 0x142860;
virtual void sceneWillResume() = win 0x4fb50; virtual void sceneWillResume() = win 0x4fb50;
virtual bool init() = mac 0x141c10, win 0x4de40; virtual bool init() = mac 0x141c10, win 0x4de40;
@ -910,6 +931,7 @@ class DailyLevelPage : FLAlertLayer {
static DailyLevelPage* create(bool weekly) = win 0x6a860; static DailyLevelPage* create(bool weekly) = win 0x6a860;
bool init(bool weekly) = win 0x6a900; bool init(bool weekly) = win 0x6a900;
void updateTimers(float) = win 0x6bef0; void updateTimers(float) = win 0x6bef0;
virtual void show() = mac 0x10a4b0, win 0x3f360;
PAD = win 0x21; PAD = win 0x21;
bool m_weekly; bool m_weekly;
@ -1021,7 +1043,7 @@ class EditButtonBar : cocos2d::CCNode {
} }
void addButton(CCMenuItemSpriteExtra* btn, bool reload) { void addButton(CCMenuItemSpriteExtra* btn, bool reload) {
if (this->m_buttonArray) if (this->m_buttonArray)
this->m_buttonArray->addObject(static_cast<cocos2d::CCObject*>(btn)); this->m_buttonArray->addObject(btn);
if (reload) if (reload)
this->reloadItemsInNormalSize(); this->reloadItemsInNormalSize();
} }
@ -1040,7 +1062,7 @@ class EditLevelLayer : cocos2d::CCLayer, FLAlertLayerProtocol, TextInputDelegate
static void scene(GJGameLevel* level) { static void scene(GJGameLevel* level) {
auto scene = cocos2d::CCScene::create(); auto scene = cocos2d::CCScene::create();
scene->addChild(static_cast<cocos2d::CCNode*>(EditLevelLayer::create(level))); scene->addChild(EditLevelLayer::create(level));
cocos2d::CCDirector::sharedDirector()->replaceScene( cocos2d::CCDirector::sharedDirector()->replaceScene(
cocos2d::CCTransitionFade::create(.5f, scene) cocos2d::CCTransitionFade::create(.5f, scene)
@ -4826,6 +4848,7 @@ class SelectArtLayer {
} }
class SetGroupIDLayer : FLAlertLayer, TextInputDelegate { class SetGroupIDLayer : FLAlertLayer, TextInputDelegate {
bool init(GameObject* object, cocos2d::CCArray* objects) = mac 0x1947c0, win 0x22b670;
void onNextGroupID1(cocos2d::CCObject*) = mac 0x1967a0, win 0x22d790; void onNextGroupID1(cocos2d::CCObject*) = mac 0x1967a0, win 0x22d790;
void textChanged(CCTextInputNode*) = mac 0x197af0, win 0x22d610; void textChanged(CCTextInputNode*) = mac 0x197af0, win 0x22d610;
void updateGroupIDLabel() = mac 0x197260, win 0x22e450; void updateGroupIDLabel() = mac 0x197260, win 0x22e450;

View file

@ -1,513 +1,2 @@
#pragma once #include "gnustl.hpp"
// #include "msvcstl.hpp"
#include <string>
#include <map>
#include <vector>
#include <iostream>
#include <variant> // for std::monostate
#include <algorithm>
#include <Geode/platform/platform.hpp>
//#include "../utils/platform.hpp"
namespace geode::base {
uintptr_t get();
}
#if defined(GEODE_IS_MACOS) || defined(GEODE_IS_ANDROID)
namespace gd {
struct _internal_string {
size_t m_len;
size_t m_capacity;
int m_refcount;
};
class GEODE_DLL string {
public:
string();
string(char const* ok);
string(std::string ok) : string(ok.c_str()) {}
operator std::string() const {
return std::string((char*)m_data, m_data[-1].m_len);
}
bool operator==(string const& other) const;
string(string const& ok);
string& operator=(char const* ok);
string& operator=(string const& ok);
__attribute__((noinline)) ~string();
char const* c_str() const { return (char const*)m_data; }
size_t size() const { return m_data[-1].m_len; }
protected:
_internal_string* m_data;
};
struct _rb_tree_base {
bool m_isblack;
_rb_tree_base* m_parent;
_rb_tree_base* m_left;
_rb_tree_base* m_right;
};
template<typename T>
struct _rb_tree_node : public _rb_tree_base {
T m_value;
};
static void _rb_tree_rotate_left(_rb_tree_base* const x, _rb_tree_base*& root) {
_rb_tree_base* const y = x->m_right;
x->m_right = y->m_left;
if (y->m_left !=0)
y->m_left->m_parent = x;
y->m_parent = x->m_parent;
if (x == root)
root = y;
else if (x == x->m_parent->m_left)
x->m_parent->m_left = y;
else
x->m_parent->m_right = y;
y->m_left = x;
x->m_parent = y;
}
static void _rb_tree_rotate_right(_rb_tree_base* const x, _rb_tree_base*& root) {
_rb_tree_base* const y = x->m_left;
x->m_left = y->m_right;
if (y->m_right != 0)
y->m_right->m_parent = x;
y->m_parent = x->m_parent;
if (x == root)
root = y;
else if (x == x->m_parent->m_right)
x->m_parent->m_right = y;
else
x->m_parent->m_left = y;
y->m_right = x;
x->m_parent = y;
}
static void _rb_insert_rebalance(const bool insert_left, _rb_tree_base* x, _rb_tree_base* p, _rb_tree_base& header) {
_rb_tree_base *& root = header.m_parent;
x->m_parent = p;
x->m_left = 0;
x->m_right = 0;
x->m_isblack = false;
if (insert_left) {
p->m_left = x;
if (p == &header) {
header.m_parent = x;
header.m_right = x;
} else if (p == header.m_left){
header.m_left = x;
}
} else {
p->m_right = x;
if (p == header.m_right) {
header.m_right = x;
}
}
while (x != root && x->m_parent->m_isblack == false) {
_rb_tree_base* const xpp = x->m_parent->m_parent;
if (x->m_parent == xpp->m_left) {
_rb_tree_base* const y = xpp->m_right;
if (y && y->m_isblack == false) {
x->m_parent->m_isblack = true;
y->m_isblack = true;
xpp->m_isblack = false;
x = xpp;
} else {
if (x == x->m_parent->m_right) {
x = x->m_parent;
_rb_tree_rotate_left(x, root);
}
x->m_parent->m_isblack = true;
xpp->m_isblack = false;
_rb_tree_rotate_right(xpp, root);
}
} else {
_rb_tree_base* const y = xpp->m_left;
if (y && y->m_isblack == false) {
x->m_parent->m_isblack = true;
y->m_isblack = true;
xpp->m_isblack = false;
x = xpp;
} else {
if (x == x->m_parent->m_left) {
x = x->m_parent;
_rb_tree_rotate_right(x, root);
}
x->m_parent->m_isblack = true;
xpp->m_isblack = false;
_rb_tree_rotate_left(xpp, root);
}
}
}
root->m_isblack = true;
}
static _rb_tree_base* _rb_increment(_rb_tree_base* __x) throw () {
if (__x->m_right != 0) {
__x = __x->m_right;
while (__x->m_left != 0)
__x = __x->m_left;
} else {
_rb_tree_base* __y = __x->m_parent;
while (__x == __y->m_right) {
__x = __y;
__y = __y->m_parent;
}
if (__x->m_right != __y)
__x = __y;
}
return __x;
}
static _rb_tree_base* _rb_decrement(_rb_tree_base* __x) throw () {
if (!__x->m_isblack && __x->m_parent->m_parent == __x)
__x = __x->m_right;
else if (__x->m_left != 0) {
_rb_tree_base* __y = __x->m_left;
while (__y->m_right != 0)
__y = __y->m_right;
__x = __y;
} else {
_rb_tree_base* __y = __x->m_parent;
while (__x == __y->m_left) {
__x = __y;
__y = __y->m_parent;
}
__x = __y;
}
return __x;
}
template <typename K, typename V>
class GEODE_DLL map {
protected:
std::less<K> compare;
_rb_tree_base m_header;
size_t m_nodecount;
public:
typedef _rb_tree_node<std::pair<K,V> >* _tree_node;
std::map<K, V> std() {
return (std::map<K, V>)(*this);
}
operator std::map<K, V>() {
auto iter_node = static_cast<_tree_node>(m_header.m_left);
auto end_node = static_cast<_tree_node>(&m_header);
std::map<K, V> out;
for (;iter_node != end_node; iter_node = static_cast<_tree_node>(_rb_increment(iter_node))) {
out[iter_node->m_value.first] = iter_node->m_value.second;
}
return out;
}
operator std::map<K, V>() const {
auto iter_node = static_cast<_tree_node>(m_header.m_left);
auto end_node = (_tree_node)(&m_header);
std::map<K, V> out;
for (;iter_node != end_node; iter_node = static_cast<_tree_node>(_rb_increment(iter_node))) {
out[iter_node->m_value.first] = iter_node->m_value.second;
}
return out;
}
void insert(_tree_node x, _tree_node p, const std::pair<K, V>& val) {
bool insert_left = (x != 0 || p == static_cast<_tree_node>(&m_header) || val.first < p->m_value.first);
_tree_node z = new _rb_tree_node<std::pair<K,V> >();
z->m_value = val;
_rb_insert_rebalance(insert_left, z, p, m_header);
++m_nodecount;
}
void insert_pair(const std::pair<K, V>& val) {
_tree_node x = static_cast<_tree_node>(m_header.m_parent);
_tree_node y = static_cast<_tree_node>(&m_header);
bool comp = true;
while (x != 0) {
y = x;
comp = val.first < x->m_value.first;
x = comp ? static_cast<_tree_node>(x->m_left) : static_cast<_tree_node>(x->m_right);
}
auto iter = y;
if (comp) {
if (iter == static_cast<_tree_node>(m_header.m_left)) {
insert(x, y, val);
} else {
iter = static_cast<_tree_node>(_rb_decrement(iter));
}
}
if (iter->m_value.first < val.first) {
insert(x, y, val);
}
}
map(std::map<K, V> input) {
m_header.m_isblack = false;
m_header.m_parent = 0;
m_header.m_left = &m_header;
m_header.m_right = &m_header;
for (auto i : input) {
insert_pair(i);
}
}
void erase(_tree_node x) {
while (x != 0) {
erase(static_cast<_tree_node>(x->m_right));
auto y = static_cast<_tree_node>(x->m_left);
delete y;
x = y;
}
}
map(map const& lol) : map(std::map<K, V>(lol)) {}
map() : map(std::map<K, V>()) {}
~map() {
erase(static_cast<_tree_node>(m_header.m_parent));
}
};
template <typename T>
class GEODE_DLL vector {
public:
using value_type = T;
operator std::vector<T>() const {
std::vector<T> out;
for (auto i = m_start; i != m_finish; ++i) {
out.push_back(*i);
}
return out;
}
vector(std::vector<T> input) {
auto tmp = new T[input.size()];
m_start = tmp;
m_finish = m_start + input.size();
m_capacity_end = m_start + input.size();
for (auto i : input) {
*tmp = i;
tmp++;
}
}
vector(std::initializer_list<T> const& input) {
auto tmp = new T[input.size()];
m_start = tmp;
m_finish = m_start + input.size();
m_capacity_end = m_start + input.size();
std::copy(input.begin(), input.end(), tmp);
}
T& front() {
return *m_start;
}
auto begin() { return m_start; }
auto end() { return m_finish; }
auto begin() const { return static_cast<const T*>(m_start); }
auto end() const { return static_cast<const T*>(m_finish); }
vector(vector const& lol) : vector(std::vector<T>(lol)) {}
vector() : vector(std::vector<T>()) {}
~vector() {
delete[] m_start;
}
protected:
T* m_start;
T* m_finish;
T* m_capacity_end;
};
struct _bit_reference {
uintptr_t* m_bitptr;
uintptr_t m_mask;
_bit_reference(uintptr_t* x, uintptr_t y) : m_bitptr(x), m_mask(y) {}
_bit_reference() : m_bitptr(0), m_mask(0) {}
operator bool() const {
return !!(*m_bitptr & m_mask);
}
_bit_reference& operator=(bool x) {
if (x)
*m_bitptr |= m_mask;
else
*m_bitptr &= ~m_mask;
return *this;
}
_bit_reference& operator=(const _bit_reference& x) {
return *this = bool(x);
}
bool operator==(const _bit_reference& x) const {
return bool(*this) == bool(x);
}
bool operator<(const _bit_reference& x) const {
return !bool(*this) && bool(x);
}
void flip() {
*m_bitptr ^= m_mask;
}
};
struct _bit_iterator {
uintptr_t* m_bitptr;
unsigned int m_offset;
_bit_iterator(uintptr_t* x) : m_bitptr(x), m_offset(0) {}
_bit_iterator(uintptr_t* x, unsigned o) : m_bitptr(x), m_offset(o) {}
_bit_reference operator*() const {
return _bit_reference(m_bitptr, 1UL << m_offset);
}
_bit_iterator& operator++() {
if (m_offset++ == sizeof(uintptr_t)-1) {
m_offset = 0;
m_bitptr++;
}
return *this;
}
bool operator!=(const _bit_iterator& b) {
return !(m_bitptr == b.m_bitptr && m_offset == b.m_offset);
}
};
template <>
class vector<bool> {
protected:
_bit_iterator m_start;
_bit_iterator m_end;
uintptr_t* m_capacity_end;
public:
vector(std::vector<bool> input) : m_start(0), m_end(0) {
auto realsize = input.size()/int(sizeof(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;
}
}
operator std::vector<bool>() {
std::vector<bool> out;
for (auto i = m_start; i != m_end; ++i) {
out.push_back(*i);
}
return out;
}
operator std::vector<bool>() const {
std::vector<bool> out;
for (auto i = m_start; i != m_end; ++i) {
out.push_back(*i);
}
return out;
}
vector(vector<bool> const& lol) : vector(std::vector<bool>(lol)) {}
vector() : vector(std::vector<bool>()) {}
~vector() {
delete[] m_start.m_bitptr;
}
};
};
#elif defined(GEODE_IS_IOS)
namespace gd {
class GEODE_DLL string {
public:
string() {}
string(char const* ok) : m_internal(ok) {}
string(std::string ok) : m_internal(ok) {}
operator std::string() {
return m_internal;
}
operator std::string() const {
return m_internal;
}
string(string const& ok) : m_internal(ok) {}
string& operator=(char const* ok) {m_internal = ok; return *this;}
string& operator=(string const& ok) {m_internal = ok; return *this;}
~string() {}
char const* c_str() const {return m_internal.c_str(); }
protected:
std::string m_internal;
};
template <typename T>
class GEODE_DLL vector {
public:
using value_type = T;
operator std::vector<T>() {
return m_internal;
}
operator std::vector<T>() const {
return m_internal;
}
vector(std::vector<T> input) : m_internal(input) {}
T& front() {
return m_internal.front();
}
vector(vector const& lol) : m_internal(lol) {}
vector() : m_internal() {}
~vector() {}
protected:
std::vector<T> m_internal;
};
template <typename K, typename V>
class GEODE_DLL map {
protected:
std::map<K, V> m_internal;
public:
operator std::map<K, V>() {
return m_internal;
}
operator std::map<K, V>() const {
return m_internal;
}
map(std::map<K, V> input) : m_internal(input) {}
map(map const& lol) : m_internal(lol) {}
map() {}
~map() {}
};
}
#else
namespace gd = std;
#endif

View file

@ -0,0 +1,512 @@
#pragma once
#include <string>
#include <map>
#include <vector>
#include <algorithm>
#include <Geode/platform/platform.hpp>
// #include <Geode/binding/GDString.hpp>
//#include "../utils/platform.hpp"
namespace geode::base {
uintptr_t get();
}
#if defined(GEODE_IS_MACOS) || defined(GEODE_IS_ANDROID)
namespace gd {
struct _internal_string {
size_t m_len;
size_t m_capacity;
int m_refcount;
};
class GEODE_DLL string {
public:
string();
string(char const* ok);
string(std::string ok) : string(ok.c_str()) {}
operator std::string() const {
return std::string((char*)m_data, m_data[-1].m_len);
}
bool operator==(string const& other) const;
string(string const& ok);
string& operator=(char const* ok);
string& operator=(string const& ok);
__attribute__((noinline)) ~string();
char const* c_str() const { return (char const*)m_data; }
size_t size() const { return m_data[-1].m_len; }
protected:
_internal_string* m_data;
};
struct _rb_tree_base {
bool m_isblack;
_rb_tree_base* m_parent;
_rb_tree_base* m_left;
_rb_tree_base* m_right;
};
template<typename T>
struct _rb_tree_node : public _rb_tree_base {
T m_value;
};
static void _rb_tree_rotate_left(_rb_tree_base* const x, _rb_tree_base*& root) {
_rb_tree_base* const y = x->m_right;
x->m_right = y->m_left;
if (y->m_left !=0)
y->m_left->m_parent = x;
y->m_parent = x->m_parent;
if (x == root)
root = y;
else if (x == x->m_parent->m_left)
x->m_parent->m_left = y;
else
x->m_parent->m_right = y;
y->m_left = x;
x->m_parent = y;
}
static void _rb_tree_rotate_right(_rb_tree_base* const x, _rb_tree_base*& root) {
_rb_tree_base* const y = x->m_left;
x->m_left = y->m_right;
if (y->m_right != 0)
y->m_right->m_parent = x;
y->m_parent = x->m_parent;
if (x == root)
root = y;
else if (x == x->m_parent->m_right)
x->m_parent->m_right = y;
else
x->m_parent->m_left = y;
y->m_right = x;
x->m_parent = y;
}
static void _rb_insert_rebalance(const bool insert_left, _rb_tree_base* x, _rb_tree_base* p, _rb_tree_base& header) {
_rb_tree_base *& root = header.m_parent;
x->m_parent = p;
x->m_left = 0;
x->m_right = 0;
x->m_isblack = false;
if (insert_left) {
p->m_left = x;
if (p == &header) {
header.m_parent = x;
header.m_right = x;
} else if (p == header.m_left){
header.m_left = x;
}
} else {
p->m_right = x;
if (p == header.m_right) {
header.m_right = x;
}
}
while (x != root && x->m_parent->m_isblack == false) {
_rb_tree_base* const xpp = x->m_parent->m_parent;
if (x->m_parent == xpp->m_left) {
_rb_tree_base* const y = xpp->m_right;
if (y && y->m_isblack == false) {
x->m_parent->m_isblack = true;
y->m_isblack = true;
xpp->m_isblack = false;
x = xpp;
} else {
if (x == x->m_parent->m_right) {
x = x->m_parent;
_rb_tree_rotate_left(x, root);
}
x->m_parent->m_isblack = true;
xpp->m_isblack = false;
_rb_tree_rotate_right(xpp, root);
}
} else {
_rb_tree_base* const y = xpp->m_left;
if (y && y->m_isblack == false) {
x->m_parent->m_isblack = true;
y->m_isblack = true;
xpp->m_isblack = false;
x = xpp;
} else {
if (x == x->m_parent->m_left) {
x = x->m_parent;
_rb_tree_rotate_right(x, root);
}
x->m_parent->m_isblack = true;
xpp->m_isblack = false;
_rb_tree_rotate_left(xpp, root);
}
}
}
root->m_isblack = true;
}
static _rb_tree_base* _rb_increment(_rb_tree_base* __x) throw () {
if (__x->m_right != 0) {
__x = __x->m_right;
while (__x->m_left != 0)
__x = __x->m_left;
} else {
_rb_tree_base* __y = __x->m_parent;
while (__x == __y->m_right) {
__x = __y;
__y = __y->m_parent;
}
if (__x->m_right != __y)
__x = __y;
}
return __x;
}
static _rb_tree_base* _rb_decrement(_rb_tree_base* __x) throw () {
if (!__x->m_isblack && __x->m_parent->m_parent == __x)
__x = __x->m_right;
else if (__x->m_left != 0) {
_rb_tree_base* __y = __x->m_left;
while (__y->m_right != 0)
__y = __y->m_right;
__x = __y;
} else {
_rb_tree_base* __y = __x->m_parent;
while (__x == __y->m_left) {
__x = __y;
__y = __y->m_parent;
}
__x = __y;
}
return __x;
}
template <typename K, typename V>
class GEODE_DLL map {
protected:
std::less<K> compare;
_rb_tree_base m_header;
size_t m_nodecount;
public:
typedef _rb_tree_node<std::pair<K,V> >* _tree_node;
std::map<K, V> std() {
return (std::map<K, V>)(*this);
}
operator std::map<K, V>() {
auto iter_node = static_cast<_tree_node>(m_header.m_left);
auto end_node = static_cast<_tree_node>(&m_header);
std::map<K, V> out;
for (;iter_node != end_node; iter_node = static_cast<_tree_node>(_rb_increment(iter_node))) {
out[iter_node->m_value.first] = iter_node->m_value.second;
}
return out;
}
operator std::map<K, V>() const {
auto iter_node = static_cast<_tree_node>(m_header.m_left);
auto end_node = (_tree_node)(&m_header);
std::map<K, V> out;
for (;iter_node != end_node; iter_node = static_cast<_tree_node>(_rb_increment(iter_node))) {
out[iter_node->m_value.first] = iter_node->m_value.second;
}
return out;
}
void insert(_tree_node x, _tree_node p, const std::pair<K, V>& val) {
bool insert_left = (x != 0 || p == static_cast<_tree_node>(&m_header) || val.first < p->m_value.first);
_tree_node z = new _rb_tree_node<std::pair<K,V> >();
z->m_value = val;
_rb_insert_rebalance(insert_left, z, p, m_header);
++m_nodecount;
}
void insert_pair(const std::pair<K, V>& val) {
_tree_node x = static_cast<_tree_node>(m_header.m_parent);
_tree_node y = static_cast<_tree_node>(&m_header);
bool comp = true;
while (x != 0) {
y = x;
comp = val.first < x->m_value.first;
x = comp ? static_cast<_tree_node>(x->m_left) : static_cast<_tree_node>(x->m_right);
}
auto iter = y;
if (comp) {
if (iter == static_cast<_tree_node>(m_header.m_left)) {
insert(x, y, val);
} else {
iter = static_cast<_tree_node>(_rb_decrement(iter));
}
}
if (iter->m_value.first < val.first) {
insert(x, y, val);
}
}
map(std::map<K, V> input) {
m_header.m_isblack = false;
m_header.m_parent = 0;
m_header.m_left = &m_header;
m_header.m_right = &m_header;
for (auto i : input) {
insert_pair(i);
}
}
void erase(_tree_node x) {
while (x != 0) {
erase(static_cast<_tree_node>(x->m_right));
auto y = static_cast<_tree_node>(x->m_left);
delete y;
x = y;
}
}
map(map const& lol) : map(std::map<K, V>(lol)) {}
map() : map(std::map<K, V>()) {}
~map() {
erase(static_cast<_tree_node>(m_header.m_parent));
}
};
template <typename T>
class GEODE_DLL vector {
public:
using value_type = T;
operator std::vector<T>() const {
std::vector<T> out;
for (auto i = m_start; i != m_finish; ++i) {
out.push_back(*i);
}
return out;
}
vector(std::vector<T> input) {
auto tmp = new T[input.size()];
m_start = tmp;
m_finish = m_start + input.size();
m_capacity_end = m_start + input.size();
for (auto i : input) {
*tmp = i;
tmp++;
}
}
vector(std::initializer_list<T> const& input) {
auto tmp = new T[input.size()];
m_start = tmp;
m_finish = m_start + input.size();
m_capacity_end = m_start + input.size();
std::copy(input.begin(), input.end(), tmp);
}
T& front() {
return *m_start;
}
auto begin() { return m_start; }
auto end() { return m_finish; }
auto begin() const { return static_cast<const T*>(m_start); }
auto end() const { return static_cast<const T*>(m_finish); }
vector(vector const& lol) : vector(std::vector<T>(lol)) {}
vector() : vector(std::vector<T>()) {}
~vector() {
delete[] m_start;
}
protected:
T* m_start;
T* m_finish;
T* m_capacity_end;
};
struct _bit_reference {
uintptr_t* m_bitptr;
uintptr_t m_mask;
_bit_reference(uintptr_t* x, uintptr_t y) : m_bitptr(x), m_mask(y) {}
_bit_reference() : m_bitptr(0), m_mask(0) {}
operator bool() const {
return !!(*m_bitptr & m_mask);
}
_bit_reference& operator=(bool x) {
if (x)
*m_bitptr |= m_mask;
else
*m_bitptr &= ~m_mask;
return *this;
}
_bit_reference& operator=(const _bit_reference& x) {
return *this = bool(x);
}
bool operator==(const _bit_reference& x) const {
return bool(*this) == bool(x);
}
bool operator<(const _bit_reference& x) const {
return !bool(*this) && bool(x);
}
void flip() {
*m_bitptr ^= m_mask;
}
};
struct _bit_iterator {
uintptr_t* m_bitptr;
unsigned int m_offset;
_bit_iterator(uintptr_t* x) : m_bitptr(x), m_offset(0) {}
_bit_iterator(uintptr_t* x, unsigned o) : m_bitptr(x), m_offset(o) {}
_bit_reference operator*() const {
return _bit_reference(m_bitptr, 1UL << m_offset);
}
_bit_iterator& operator++() {
if (m_offset++ == sizeof(uintptr_t)-1) {
m_offset = 0;
m_bitptr++;
}
return *this;
}
bool operator!=(const _bit_iterator& b) {
return !(m_bitptr == b.m_bitptr && m_offset == b.m_offset);
}
};
template <>
class vector<bool> {
protected:
_bit_iterator m_start;
_bit_iterator m_end;
uintptr_t* m_capacity_end;
public:
vector(std::vector<bool> input) : m_start(0), m_end(0) {
auto realsize = input.size()/int(sizeof(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;
}
}
operator std::vector<bool>() {
std::vector<bool> out;
for (auto i = m_start; i != m_end; ++i) {
out.push_back(*i);
}
return out;
}
operator std::vector<bool>() const {
std::vector<bool> out;
for (auto i = m_start; i != m_end; ++i) {
out.push_back(*i);
}
return out;
}
vector(vector<bool> const& lol) : vector(std::vector<bool>(lol)) {}
vector() : vector(std::vector<bool>()) {}
~vector() {
delete[] m_start.m_bitptr;
}
};
};
#elif defined(GEODE_IS_IOS)
namespace gd {
class GEODE_DLL string {
public:
string() {}
string(char const* ok) : m_internal(ok) {}
string(std::string ok) : m_internal(ok) {}
operator std::string() {
return m_internal;
}
operator std::string() const {
return m_internal;
}
string(string const& ok) : m_internal(ok) {}
string& operator=(char const* ok) {m_internal = ok; return *this;}
string& operator=(string const& ok) {m_internal = ok; return *this;}
~string() {}
char const* c_str() const {return m_internal.c_str(); }
protected:
std::string m_internal;
};
template <typename T>
class GEODE_DLL vector {
public:
using value_type = T;
operator std::vector<T>() {
return m_internal;
}
operator std::vector<T>() const {
return m_internal;
}
vector(std::vector<T> input) : m_internal(input) {}
T& front() {
return m_internal.front();
}
vector(vector const& lol) : m_internal(lol) {}
vector() : m_internal() {}
~vector() {}
protected:
std::vector<T> m_internal;
};
template <typename K, typename V>
class GEODE_DLL map {
protected:
std::map<K, V> m_internal;
public:
operator std::map<K, V>() {
return m_internal;
}
operator std::map<K, V>() const {
return m_internal;
}
map(std::map<K, V> input) : m_internal(input) {}
map(map const& lol) : m_internal(lol) {}
map() {}
~map() {}
};
}
#else
namespace gd = std;
#endif

View file

@ -0,0 +1,96 @@
#pragma once
#include <string>
#include <map>
#include <vector>
#include <algorithm>
#include <functional>
#include <Geode/platform/platform.hpp>
// #include <Geode/binding/GDString.hpp>
#if defined(GEODE_IS_WINDOWS)
namespace gd {
struct InternalString {
union {
char m_storage[16];
char* m_pointer;
};
size_t m_length;
size_t m_capacity;
};
class GEODE_DLL string : protected GDString {
private:
InternalString m_data;
public:
template <class... Params>
string(Params&&... params) {
m_data.m_pointer = 0;
m_data.m_length = 0;
m_data.m_capacity = 15;
auto val = std::string(std::forward<Params>(params)...);
(void)this->winAssign(val.c_str(), val.size());
}
~string() {
(void)this->winDtor();
}
/*template <class... Params>
decltype(auto) operator=(Params&&... params) -> decltype(this->operator=(std::forward<Params>(params)...)) {
auto val = std::string(this->winCStr(), m_data.m_length);
val.operator=(std::forward<Params>(params)...);
(void)this->winAssign(val.c_str(), val.size());
}*/
template <class... Params>
string& operator=(Params&&... params) {
auto val = std::string(this->winCStr(), m_data.m_length);
val.operator=(std::forward<Params>(params)...);
(void)this->winAssign(val.c_str(), val.size());
return *this;
}
template <class... Params>
string& assign(Params&&... params) {
auto val = std::string(this->winCStr(), m_data.m_length);
val.assign(std::forward<Params>(params)...);
(void)this->winAssign(val.c_str(), val.size());
return *this;
}
char& at(size_t pos) {
if (pos >= m_data.m_length) throw std::out_of_range("gd::string::at");
}
char const& at(size_t pos) const {
if (pos >= m_data.m_length) throw std::out_of_range("gd::string::at");
}
char& operator[](size_t pos) {
return this->winCStr()[pos];
}
char const& operator[](size_t pos) const {
return this->winCStr()[pos];
}
char* data() {
return this->winCStr();
}
char const* data() const {
return this->winCStr();
}
char const* c_str() const {
return this->winCStr();
}
};
}
#endif

View file

@ -1,21 +1,23 @@
#pragma once #pragma once
#include <Geode/DefaultInclude.hpp>
#include "Types.hpp"
#include "Hook.hpp" #include "Hook.hpp"
#include <Geode/utils/types.hpp> #include "Setting.hpp"
#include "Types.hpp"
#include <Geode/DefaultInclude.hpp>
#include <Geode/utils/Result.hpp> #include <Geode/utils/Result.hpp>
#include <Geode/utils/VersionInfo.hpp> #include <Geode/utils/VersionInfo.hpp>
#include <Geode/utils/json.hpp> #include <Geode/utils/json.hpp>
#include <string_view> #include <Geode/utils/types.hpp>
#include <vector>
#include <unordered_map>
#include <type_traits>
#include "Setting.hpp"
#include <optional> #include <optional>
#include <string_view>
#include <type_traits>
#include <unordered_map>
#include <vector>
class InternalLoader; class InternalLoader;
class InternalMod; class InternalMod;
namespace geode { namespace geode {
struct PlatformInfo; struct PlatformInfo;
@ -26,8 +28,8 @@ namespace geode {
class Setting; class Setting;
class Unknown; class Unknown;
using unknownmemfn_t = void(Unknown::*)(); using unknownmemfn_t = void (Unknown::*)();
using unknownfn_t = void(*)(); using unknownfn_t = void (*)();
} }
/** /**
@ -35,7 +37,7 @@ namespace geode {
*/ */
GEODE_API bool GEODE_CALL geode_implicit_load(geode::Mod*); GEODE_API bool GEODE_CALL geode_implicit_load(geode::Mod*);
namespace geode { namespace geode {
struct Dependency { struct Dependency {
std::string m_id; std::string m_id;
@ -53,7 +55,7 @@ namespace geode {
}; };
/** /**
* Represents all the data gatherable * Represents all the data gatherable
* from mod.json * from mod.json
*/ */
struct GEODE_DLL ModInfo { struct GEODE_DLL ModInfo {
@ -62,13 +64,15 @@ namespace geode {
*/ */
ghc::filesystem::path m_path; ghc::filesystem::path m_path;
/** /**
* Name of the platform binary within * Name of the platform binary within
* the mod zip * the mod zip
*/ */
// clang-format off
std::string m_binaryName = GEODE_WINDOWS("mod.dll") std::string m_binaryName = GEODE_WINDOWS("mod.dll")
GEODE_MACOS("mod.dylib") GEODE_MACOS("mod.dylib")
GEODE_IOS("mod.dylib") GEODE_IOS("mod.dylib")
GEODE_ANDROID("mod.so"); GEODE_ANDROID("mod.so");
// clang-format on
/** /**
* Mod Version. Should follow semver. * Mod Version. Should follow semver.
*/ */
@ -103,12 +107,12 @@ namespace geode {
*/ */
std::string m_developer; std::string m_developer;
/** /**
* Short & concise description of the * Short & concise description of the
* mod. * mod.
*/ */
std::optional<std::string> m_description; std::optional<std::string> m_description;
/** /**
* Detailed description of the mod, writtenin Markdown (see * Detailed description of the mod, writtenin Markdown (see
* <Geode/ui/MDTextArea.hpp>) for more info * <Geode/ui/MDTextArea.hpp>) for more info
*/ */
std::optional<std::string> m_details; std::optional<std::string> m_details;
@ -118,8 +122,8 @@ namespace geode {
*/ */
std::optional<std::string> m_changelog; std::optional<std::string> m_changelog;
/** /**
* Support info for the mod; this means anything to show ways to * Support info for the mod; this means anything to show ways to
* support the mod's development, like donations. Written in Markdown * support the mod's development, like donations. Written in Markdown
* (see <Geode/ui/MDTextArea.hpp>) for more info * (see <Geode/ui/MDTextArea.hpp>) for more info
*/ */
std::optional<std::string> m_supportInfo; std::optional<std::string> m_supportInfo;
@ -170,8 +174,8 @@ namespace geode {
private: private:
/** /**
* Version is passed for backwards * Version is passed for backwards
* compatibility if we update the mod.json * compatibility if we update the mod.json
* format * format
*/ */
static Result<ModInfo> createFromSchemaV010(ModJson const& json); static Result<ModInfo> createFromSchemaV010(ModJson const& json);
@ -179,10 +183,7 @@ namespace geode {
Result<> addSpecialFiles(ghc::filesystem::path const& dir); Result<> addSpecialFiles(ghc::filesystem::path const& dir);
Result<> addSpecialFiles(cocos2d::ZipFile& zip); Result<> addSpecialFiles(cocos2d::ZipFile& zip);
std::vector<std::pair< std::vector<std::pair<std::string, std::optional<std::string>*>> getSpecialFiles();
std::string,
std::optional<std::string>*
>> getSpecialFiles();
}; };
/** /**
@ -195,7 +196,7 @@ namespace geode {
Mod* m_mod; Mod* m_mod;
DataStore(Mod* m, nlohmann::json& j) : m_mod(m), m_store(j) {} DataStore(Mod* m, nlohmann::json& j) : m_mod(m), m_store(j) {}
friend class Mod; friend class Mod;
public: public:
@ -206,12 +207,11 @@ namespace geode {
DataStore& operator=(nlohmann::json&); DataStore& operator=(nlohmann::json&);
bool contains(std::string const&) const; bool contains(std::string const&) const;
operator nlohmann::json(); operator nlohmann::json();
}; };
/** /**
* @class Mod * @class Mod
* Represents a Mod ingame. * Represents a Mod ingame.
* @abstract * @abstract
*/ */
class GEODE_DLL Mod { class GEODE_DLL Mod {
@ -253,9 +253,9 @@ namespace geode {
*/ */
ghc::filesystem::path m_saveDirPath; ghc::filesystem::path m_saveDirPath;
/** /**
* Pointers to mods that depend on * Pointers to mods that depend on
* this Mod. Makes it possible to * this Mod. Makes it possible to
* enable / disable them automatically, * enable / disable them automatically,
* when their dependency is disabled. * when their dependency is disabled.
*/ */
std::vector<Mod*> m_parentDependencies; std::vector<Mod*> m_parentDependencies;
@ -283,7 +283,7 @@ namespace geode {
geode_save_data m_saveDataFunc = nullptr; geode_save_data m_saveDataFunc = nullptr;
geode_setting_updated m_settingUpdatedFunc = nullptr; geode_setting_updated m_settingUpdatedFunc = nullptr;
/** /**
* Whether temp/<mod id>/resources should be * Whether temp/<mod id>/resources should be
* added to CCFileUtils search paths * added to CCFileUtils search paths
*/ */
bool m_addResourcesToSearchPath = false; bool m_addResourcesToSearchPath = false;
@ -312,9 +312,9 @@ namespace geode {
static bool validateID(std::string const& id); static bool validateID(std::string const& id);
// no copying // no copying
Mod(Mod const&) = delete; Mod(Mod const&) = delete;
Mod operator=(Mod const&) = delete; Mod operator=(Mod const&) = delete;
/** /**
* Protected constructor/destructor * Protected constructor/destructor
*/ */
@ -328,10 +328,10 @@ namespace geode {
friend struct ModInfo; friend struct ModInfo;
friend class DataStore; friend class DataStore;
template<class = void> template <class = void>
static inline GEODE_HIDDEN Mod* sharedMod = nullptr; static inline GEODE_HIDDEN Mod* sharedMod = nullptr;
template<class = void> template <class = void>
static inline GEODE_HIDDEN void setSharedMod(Mod* mod) { static inline GEODE_HIDDEN void setSharedMod(Mod* mod) {
sharedMod<> = mod; sharedMod<> = mod;
} }
@ -344,17 +344,16 @@ namespace geode {
std::string getDeveloper() const; std::string getDeveloper() const;
std::optional<std::string> getDescription() const; std::optional<std::string> getDescription() const;
std::optional<std::string> getDetails() const; std::optional<std::string> getDetails() const;
[[deprecated("Use Mod::getPackagePath instead")]] [[deprecated("Use Mod::getPackagePath instead")]] std::string getPath() const;
std::string getPath() const;
ghc::filesystem::path getPackagePath() const; ghc::filesystem::path getPackagePath() const;
VersionInfo getVersion() const; VersionInfo getVersion() const;
bool isEnabled() const; bool isEnabled() const;
bool isLoaded() const; bool isLoaded() const;
bool supportsDisabling() const; bool supportsDisabling() const;
bool supportsUnloading() const; bool supportsUnloading() const;
bool wasSuccesfullyLoaded() const; bool wasSuccesfullyLoaded() const;
std::string getLoadErrorInfo() const; std::string getLoadErrorInfo() const;
ModInfo getModInfo() const; ModInfo getModInfo() const;
ghc::filesystem::path getTempDir() const; ghc::filesystem::path getTempDir() const;
ghc::filesystem::path getBinaryPath() const; ghc::filesystem::path getBinaryPath() const;
/** /**
@ -370,16 +369,16 @@ namespace geode {
decltype(ModInfo::m_settings) getSettings() const; decltype(ModInfo::m_settings) getSettings() const;
bool hasSetting(std::string const& key) const; bool hasSetting(std::string const& key) const;
std::shared_ptr<Setting> getSetting(std::string const& key) const; std::shared_ptr<Setting> getSetting(std::string const& key) const;
template<class T>
template <class T>
T getSettingValue(std::string const& key) const { T getSettingValue(std::string const& key) const {
if (this->hasSetting(key)) { if (this->hasSetting(key)) {
return geode::getBuiltInSettingValue<T>( return geode::getBuiltInSettingValue<T>(this->getSetting(key));
this->getSetting(key)
);
} }
return T(); return T();
} }
template<class T>
template <class T>
bool setSettingValue(std::string const& key, T const& value) { bool setSettingValue(std::string const& key, T const& value) {
if (this->hasSetting(key)) { if (this->hasSetting(key)) {
geode::setBuiltInSettingValue<T>(this->getSetting(key), value); geode::setBuiltInSettingValue<T>(this->getSetting(key), value);
@ -393,7 +392,7 @@ namespace geode {
* @returns nullptr if Interface is not initialized, * @returns nullptr if Interface is not initialized,
* the mod pointer if it is initialized * the mod pointer if it is initialized
*/ */
template<class = void> template <class = void>
static inline GEODE_HIDDEN Mod* get() { static inline GEODE_HIDDEN Mod* get() {
return sharedMod<>; return sharedMod<>;
} }
@ -405,59 +404,59 @@ namespace geode {
std::vector<Hook*> getHooks() const; std::vector<Hook*> getHooks() const;
/** /**
* Create a hook at an address. Call the original * Create a hook at an address. Call the original
* function by calling the original function * function by calling the original function
* no trampoline needed * no trampoline needed
* @param address The absolute address of * @param address The absolute address of
* the function to hook, i.e. gd_base + 0xXXXX * the function to hook, i.e. gd_base + 0xXXXX
* @param detour Pointer to your detour function * @param detour Pointer to your detour function
* @returns Successful result containing the * @returns Successful result containing the
* Hook handle, errorful result with info on * Hook handle, errorful result with info on
* error * error
*/ */
template<auto Detour, template <class, class...> class Convention> template <auto Detour, template <class, class...> class Convention>
Result<Hook*> addHook(void* address) { Result<Hook*> addHook(void* address) {
return this->addHook<Detour, Convention>("", address); return this->addHook<Detour, Convention>("", address);
} }
/** /**
* Create a hook at an address. Call the original * Create a hook at an address. Call the original
* function by calling the original function * function by calling the original function
* no trampoline needed. Also takes a displayName * no trampoline needed. Also takes a displayName
* parameter to use for when visualizing the hook. * parameter to use for when visualizing the hook.
* @param address The absolute address of * @param address The absolute address of
* the function to hook, i.e. gd_base + 0xXXXX * the function to hook, i.e. gd_base + 0xXXXX
* @param detour Pointer to your detour function * @param detour Pointer to your detour function
* @returns Successful result containing the * @returns Successful result containing the
* Hook handle, errorful result with info on * Hook handle, errorful result with info on
* error * error
*/ */
template<auto Detour, template <class, class...> class Convention> template <auto Detour, template <class, class...> class Convention>
Result<Hook*> addHook(std::string const& displayName, void* address) { Result<Hook*> addHook(std::string const& displayName, void* address) {
auto hook = Hook::create<Detour, Convention>((decltype(Detour))address, displayName, this); auto hook =
return this->addHook(hook); Hook::create<Detour, Convention>((decltype(Detour))address, displayName, this);
} return this->addHook(hook);
}
Result<Hook*> addHook(Hook* hook);
Result<Hook*> addHook(Hook* hook);
/** /**
* Enable a hook owned by this Mod * Enable a hook owned by this Mod
* @returns Successful result on success, * @returns Successful result on success,
* errorful result with info on error * errorful result with info on error
*/ */
Result<> enableHook(Hook* hook); Result<> enableHook(Hook* hook);
/** /**
* Disable a hook owned by this Mod * Disable a hook owned by this Mod
* @returns Successful result on success, * @returns Successful result on success,
* errorful result with info on error * errorful result with info on error
*/ */
Result<> disableHook(Hook* hook); Result<> disableHook(Hook* hook);
/** /**
* Remove a hook owned by this Mod * Remove a hook owned by this Mod
* @returns Successful result on success, * @returns Successful result on success,
* errorful result with info on error * errorful result with info on error
*/ */
Result<> removeHook(Hook* hook); Result<> removeHook(Hook* hook);
@ -466,52 +465,52 @@ namespace geode {
* Write a patch at an address * Write a patch at an address
* @param address The address to write into * @param address The address to write into
* @param data The data to write there * @param data The data to write there
* @returns Successful result on success, * @returns Successful result on success,
* errorful result with info on error * errorful result with info on error
*/ */
Result<Patch*> patch(void* address, byte_array data); Result<Patch*> patch(void* address, byte_array data);
/** /**
* Remove a patch owned by this Mod * Remove a patch owned by this Mod
* @returns Successful result on success, * @returns Successful result on success,
* errorful result with info on error * errorful result with info on error
*/ */
Result<> unpatch(Patch* patch); Result<> unpatch(Patch* patch);
/** /**
* Load this mod * Load this mod
* @returns Successful result on success, * @returns Successful result on success,
* errorful result with info on error * errorful result with info on error
*/ */
Result<> load(); Result<> load();
/** /**
* Unload this mod * Unload this mod
* @warning May crash if the mod doesn't * @warning May crash if the mod doesn't
* properly handle unloading! * properly handle unloading!
* @returns Successful result on success, * @returns Successful result on success,
* errorful result with info on error * errorful result with info on error
*/ */
Result<> unload(); Result<> unload();
/** /**
* Enable this mod * Enable this mod
* @returns Successful result on success, * @returns Successful result on success,
* errorful result with info on error * errorful result with info on error
*/ */
Result<> enable(); Result<> enable();
/** /**
* Disable this mod if it supports doing so * Disable this mod if it supports doing so
* @returns Successful result on success, * @returns Successful result on success,
* errorful result with info on error * errorful result with info on error
*/ */
Result<> disable(); Result<> disable();
/** /**
* Disable & unload this mod (if supported), * Disable & unload this mod (if supported),
* then delete the mod's .geode file. * then delete the mod's .geode file.
* @returns Successful result on success, * @returns Successful result on success,
* errorful result with info on error * errorful result with info on error
*/ */
Result<> uninstall(); Result<> uninstall();
@ -530,39 +529,38 @@ namespace geode {
*/ */
Result<> resetDataStore(); Result<> resetDataStore();
/** /**
* Check whether or not this Mod * Check whether or not this Mod
* depends on another mod * depends on another mod
*/ */
bool depends(std::string const& id) const; bool depends(std::string const& id) const;
/** /**
* Check whether all the required * Check whether all the required
* dependencies for this mod have * dependencies for this mod have
* been loaded or not * been loaded or not
* @returns True if the mod has unresolved * @returns True if the mod has unresolved
* dependencies, false if not. * dependencies, false if not.
*/ */
bool hasUnresolvedDependencies() const; bool hasUnresolvedDependencies() const;
/** /**
* Update the state of each of the * Update the state of each of the
* dependencies. Depending on if the * dependencies. Depending on if the
* mod has unresolved dependencies, * mod has unresolved dependencies,
* it will either be loaded or unloaded * it will either be loaded or unloaded
* @returns True if the mod has unresolved * @returns True if the mod has unresolved
* dependencies, false if not. * dependencies, false if not.
*/ */
bool updateDependencyStates(); bool updateDependencyStates();
/** /**
* Get a list of all the unresolved * Get a list of all the unresolved
* dependencies this mod has * dependencies this mod has
* @returns List of all the unresolved * @returns List of all the unresolved
* dependencies * dependencies
*/ */
std::vector<Dependency> getUnresolvedDependencies(); std::vector<Dependency> getUnresolvedDependencies();
const char* expandSpriteName(const char* name); char const* expandSpriteName(char const* name);
}; };
/** /**
@ -576,6 +574,6 @@ namespace geode {
} }
} }
inline const char* operator"" _spr(const char* str, size_t) { inline char const* operator"" _spr(char const* str, size_t) {
return geode::Mod::get()->expandSpriteName(str); return geode::Mod::get()->expandSpriteName(str);
} }

View file

@ -31,7 +31,7 @@ namespace {
struct derived##Parent {}; \ struct derived##Parent {}; \
Modify<derived<derived##Parent>, base> derived##Apply; \ Modify<derived<derived##Parent>, base> derived##Apply; \
struct GEODE_HIDDEN derived##Intermediate : base { \ struct GEODE_HIDDEN derived##Intermediate : base { \
geode::modifier::FieldIntermediate<base, \ mutable geode::modifier::FieldIntermediate<base, \
derived##Intermediate, \ derived##Intermediate, \
derived<derived##Parent> \ derived<derived##Parent> \
> m_fields; \ > m_fields; \
@ -45,7 +45,7 @@ struct derived;
namespace { \ namespace { \
Modify<derived, base> derived##Apply; \ Modify<derived, base> derived##Apply; \
struct GEODE_HIDDEN derived##Intermediate : base { \ struct GEODE_HIDDEN derived##Intermediate : base { \
geode::modifier::FieldIntermediate<base, \ mutable geode::modifier::FieldIntermediate<base, \
derived##Intermediate, \ derived##Intermediate, \
derived \ derived \
> m_fields; \ > m_fields; \

View file

@ -1,18 +1,18 @@
#include <about.hpp> #include <Geode/cocos/support/zip_support/ZipUtils.h>
#include <Geode/loader/Hook.hpp> #include <Geode/loader/Hook.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/Setting.hpp> #include <Geode/loader/Setting.hpp>
#include <Geode/utils/JsonValidation.hpp>
#include <Geode/utils/conststring.hpp> #include <Geode/utils/conststring.hpp>
#include <Geode/utils/file.hpp> #include <Geode/utils/file.hpp>
#include <Geode/utils/JsonValidation.hpp>
#include <Geode/utils/map.hpp> #include <Geode/utils/map.hpp>
#include <Geode/utils/ranges.hpp>
#include <Geode/utils/string.hpp> #include <Geode/utils/string.hpp>
#include <Geode/utils/vector.hpp> #include <Geode/utils/vector.hpp>
#include <Geode/utils/ranges.hpp>
#include <InternalMod.hpp> #include <InternalMod.hpp>
#include <../support/zip_support/ZipUtils.h> #include <about.hpp>
USE_GEODE_NAMESPACE(); USE_GEODE_NAMESPACE();
@ -70,22 +70,20 @@ Result<> Mod::loadSettings() {
if (auto sett = this->getSetting(key)) { if (auto sett = this->getSetting(key)) {
// load its value // load its value
if (!sett->load(value.json())) { if (!sett->load(value.json())) {
return Err( return Err("Unable to load value for setting \"" + key + "\"");
"Unable to load value for setting \"" +
key + "\""
);
} }
} else { }
else {
log::log( log::log(
Severity::Warning, Severity::Warning, this,
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());
} }
} }
@ -94,12 +92,14 @@ Result<> Mod::loadSettings() {
auto dsPath = m_saveDirPath / "ds.json"; auto dsPath = m_saveDirPath / "ds.json";
if (!ghc::filesystem::exists(dsPath)) { if (!ghc::filesystem::exists(dsPath)) {
m_dataStore = m_info.m_defaultDataStore; m_dataStore = m_info.m_defaultDataStore;
} else { }
else {
auto dsData = utils::file::readString(dsPath); auto dsData = utils::file::readString(dsPath);
if (!dsData) return dsData; if (!dsData) return dsData;
try { try {
m_dataStore = nlohmann::json::parse(dsData.value()); m_dataStore = nlohmann::json::parse(dsData.value());
} catch(std::exception& e) { }
catch (std::exception& e) {
return Err(std::string("Unable to parse datastore: ") + e.what()); return Err(std::string("Unable to parse datastore: ") + e.what());
} }
} }
@ -151,8 +151,7 @@ Result<> Mod::createTempDir() {
if (!unzip.fileExists(m_info.m_binaryName)) { if (!unzip.fileExists(m_info.m_binaryName)) {
return Err<>( return Err<>(
"Unable to find platform binary under the name \"" + "Unable to find platform binary under the name \"" + m_info.m_binaryName + "\""
m_info.m_binaryName + "\""
); );
} }
@ -162,7 +161,7 @@ Result<> Mod::createTempDir() {
return Err<>("Unable to create temp directory for mods!"); return Err<>("Unable to create temp directory for mods!");
} }
} }
auto tempPath = ghc::filesystem::path(tempDir) / m_info.m_id; auto tempPath = ghc::filesystem::path(tempDir) / m_info.m_id;
if (!ghc::filesystem::exists(tempPath) && !ghc::filesystem::create_directories(tempPath)) { if (!ghc::filesystem::exists(tempPath) && !ghc::filesystem::create_directories(tempPath)) {
return Err<>("Unable to create temp directory"); return Err<>("Unable to create temp directory");
@ -172,11 +171,11 @@ Result<> Mod::createTempDir() {
for (auto file : unzip.getAllFiles()) { for (auto file : unzip.getAllFiles()) {
auto path = ghc::filesystem::path(file); auto path = ghc::filesystem::path(file);
if (path.has_parent_path()) { if (path.has_parent_path()) {
if ( if (!ghc::filesystem::exists(tempPath / path.parent_path()) &&
!ghc::filesystem::exists(tempPath / path.parent_path()) && !ghc::filesystem::create_directories(tempPath / path.parent_path())) {
!ghc::filesystem::create_directories(tempPath / path.parent_path()) return Err<>(
) { "Unable to create directories \"" + path.parent_path().string() + "\""
return Err<>("Unable to create directories \"" + path.parent_path().string() + "\""); );
} }
} }
unsigned long size; unsigned long size;
@ -184,10 +183,7 @@ Result<> Mod::createTempDir() {
if (!data || !size) { if (!data || !size) {
return Err<>("Unable to read \"" + std::string(file) + "\""); return Err<>("Unable to read \"" + std::string(file) + "\"");
} }
auto wrt = utils::file::writeBinary( auto wrt = utils::file::writeBinary(tempPath / file, byte_array(data, data + size));
tempPath / file,
byte_array(data, data + size)
);
if (!wrt) return Err<>("Unable to write \"" + file + "\": " + wrt.error()); if (!wrt) return Err<>("Unable to write \"" + file + "\": " + wrt.error());
} }
@ -197,12 +193,14 @@ Result<> Mod::createTempDir() {
} }
Result<> Mod::load() { Result<> Mod::load() {
if (m_loaded) { if (m_loaded) {
return Ok<>(); return Ok<>();
} }
#define RETURN_LOAD_ERR(str) \ #define RETURN_LOAD_ERR(str) \
{m_loadErrorInfo = str; \ { \
return Err<>(m_loadErrorInfo);} m_loadErrorInfo = str; \
return Err<>(m_loadErrorInfo); \
}
if (!m_tempDirName.string().size()) { if (!m_tempDirName.string().size()) {
auto err = this->createTempDir(); auto err = this->createTempDir();
@ -247,7 +245,7 @@ Result<> Mod::unload() {
if (!m_info.m_supportsUnloading) { if (!m_info.m_supportsUnloading) {
return Err<>("Mod does not support unloading"); return Err<>("Mod does not support unloading");
} }
if (m_saveDataFunc) { if (m_saveDataFunc) {
if (!m_saveDataFunc(m_saveDirPath.string().c_str())) { if (!m_saveDataFunc(m_saveDirPath.string().c_str())) {
log::log(Severity::Error, this, "Mod save data function returned false"); log::log(Severity::Error, this, "Mod save data function returned false");
@ -286,7 +284,7 @@ Result<> Mod::enable() {
if (!m_loaded) { if (!m_loaded) {
return Err<>("Mod is not loaded"); return Err<>("Mod is not loaded");
} }
if (m_enableFunc) { if (m_enableFunc) {
if (!m_enableFunc()) { if (!m_enableFunc()) {
return Err<>("Mod enable function returned false"); return Err<>("Mod enable function returned false");
@ -361,55 +359,58 @@ bool Mod::isUninstalled() const {
bool Dependency::isUnresolved() const { bool Dependency::isUnresolved() const {
return m_required && return m_required &&
(m_state == ModResolveState::Unloaded || (m_state == ModResolveState::Unloaded || m_state == ModResolveState::Unresolved ||
m_state == ModResolveState::Unresolved || m_state == ModResolveState::Disabled);
m_state == ModResolveState::Disabled);
} }
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 { }
if (!dep.m_mod->m_resolved) { else {
dep.m_mod->m_resolved = true; if (!dep.m_mod->m_resolved) {
dep.m_state = ModResolveState::Resolved; dep.m_mod->m_resolved = true;
dep.m_state = ModResolveState::Resolved;
auto r = dep.m_mod->load(); auto r = dep.m_mod->load();
if (!r) { if (!r) {
dep.m_state = ModResolveState::Unloaded; dep.m_state = ModResolveState::Unloaded;
log::log(Severity::Error, dep.m_mod, "{}", r.error()); log::log(Severity::Error, dep.m_mod, "{}", r.error());
} }
else { else {
auto r = dep.m_mod->enable(); auto r = dep.m_mod->enable();
if (!r) { if (!r) {
dep.m_state = ModResolveState::Disabled; dep.m_state = ModResolveState::Disabled;
log::log(Severity::Error, dep.m_mod, "{}", r.error()); log::log(Severity::Error, dep.m_mod, "{}", r.error());
} }
} }
} else { }
if (dep.m_mod->isEnabled()) { else {
dep.m_state = ModResolveState::Loaded; if (dep.m_mod->isEnabled()) {
} else { dep.m_state = ModResolveState::Loaded;
dep.m_state = ModResolveState::Disabled; }
} else {
} dep.m_state = ModResolveState::Disabled;
} }
} else { }
dep.m_state = ModResolveState::Unloaded; }
} }
if (dep.isUnresolved()) { else {
m_resolved = false; dep.m_state = ModResolveState::Unloaded;
}
if (dep.isUnresolved()) {
m_resolved = false;
(void)this->unload(); (void)this->unload();
hasUnresolved = true; hasUnresolved = true;
} }
} }
if (!hasUnresolved && !m_resolved) { if (!hasUnresolved && !m_resolved) {
log::debug("All dependencies for {} found", m_info.m_id); log::debug("All dependencies for {} found", m_info.m_id);
m_resolved = true; m_resolved = true;
@ -420,12 +421,13 @@ bool Mod::updateDependencyStates() {
log::error("{} Error loading: {}", this, r.error()); log::error("{} Error loading: {}", this, r.error());
} }
else { else {
auto r = this->enable(); auto r = this->enable();
if (!r) { if (!r) {
log::error("{} Error enabling: {}", this, r.error()); log::error("{} Error enabling: {}", this, r.error());
} }
} }
} 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);
} }
} }
@ -433,21 +435,21 @@ 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;
} }
std::vector<Dependency> Mod::getUnresolvedDependencies() { std::vector<Dependency> Mod::getUnresolvedDependencies() {
std::vector<Dependency> res; std::vector<Dependency> res;
for (auto const& dep : m_info.m_dependencies) { for (auto const& dep : m_info.m_dependencies) {
if (dep.isUnresolved()) { if (dep.isUnresolved()) {
res.push_back(dep); res.push_back(dep);
} }
} }
return res; return res;
} }
@ -532,14 +534,13 @@ std::vector<Hook*> Mod::getHooks() const {
} }
bool Mod::depends(std::string const& id) const { bool Mod::depends(std::string const& id) const {
return utils::ranges::contains( return utils::ranges::contains(m_info.m_dependencies, [id](Dependency const& t) {
m_info.m_dependencies, return t.m_id == id;
[id](Dependency const& t) { return t.m_id == id; } });
);
} }
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];
} }