mirror of
https://github.com/geode-sdk/geode.git
synced 2025-03-31 07:10:28 -04:00
Merge branch 'geode-sdk:main' into altalk
This commit is contained in:
commit
079daafd55
209 changed files with 4649 additions and 3041 deletions
.github/workflows
CMakeLists.txtbindings
codegen
docs
loader
CMakeLists.txt
include/Geode
CGeode.hUI.hppUtils.hpp
c++stl
cocos
external
filesystem
fmt
.clang-format
.github
.gitignoreCMakeLists.txtCONTRIBUTING.mdLICENSE.rstinclude/fmt
args.hchrono.hcolor.hcompile.hcore.hformat-inl.hformat.hlocale.hos.hostream.hprintf.hranges.hxchar.h
src
support
json
hook-core
loader
Event.hppHook.hppIPC.hppLoader.hppMod.hppModEvent.hppSetting.hppSettingEvent.hppTypes.hppcgeode.h
platform
modify
platform
ui
utils
12
.github/workflows/build.yml
vendored
12
.github/workflows/build.yml
vendored
|
@ -67,13 +67,19 @@ jobs:
|
|||
echo "${{ github.workspace }}/cli" >> $GITHUB_PATH
|
||||
|
||||
- name: Configure CMake
|
||||
run: |
|
||||
${{ matrix.config.prefixes }} cmake -B ${{ github.workspace }}/build ${{ matrix.config.extra_flags }} -DGEODE_DISABLE_CLI_CALLS=ON -DCLI_PATH="${{ github.workspace }}/cli"
|
||||
run: >
|
||||
${{ matrix.config.prefixes }} cmake -B
|
||||
${{ github.workspace }}/build
|
||||
${{ matrix.config.extra_flags }}
|
||||
-DGEODE_DISABLE_CLI_CALLS=ON
|
||||
-DCLI_PATH="${{ github.workspace }}/cli"
|
||||
-D CMAKE_C_COMPILER_LAUNCHER=ccache
|
||||
-D CMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
cd build
|
||||
cmake --build . --config RelWithDebInfo
|
||||
cmake --build . --config RelWithDebInfo --parallel
|
||||
|
||||
- name: Move to output folder
|
||||
shell: bash
|
||||
|
|
|
@ -81,8 +81,8 @@ target_link_directories(${PROJECT_NAME} INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/lo
|
|||
|
||||
add_definitions(-DFMT_CONSTEVAL=)
|
||||
|
||||
add_subdirectory(filesystem)
|
||||
add_subdirectory(fmt)
|
||||
add_subdirectory(loader/include/Geode/external/filesystem)
|
||||
add_subdirectory(loader/include/Geode/external/fmt)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} INTERFACE filesystem fmt)
|
||||
|
||||
|
|
|
@ -26,24 +26,24 @@ class cocos2d::CCApplication {
|
|||
}
|
||||
|
||||
class cocos2d::CCArray {
|
||||
auto addObject(cocos2d::CCObject*) = mac 0x419f90, ios 0x16504c;
|
||||
// auto addObject(cocos2d::CCObject*) = mac 0x419f90, ios 0x16504c;
|
||||
auto addObjectNew(cocos2d::CCObject*) = mac 0x41a450;
|
||||
auto addObjectsFromArray(cocos2d::CCArray*) = mac 0x41a2d0;
|
||||
auto containsObject(cocos2d::CCObject*) const = mac 0x41a3e0;
|
||||
auto count() const = mac 0x41a2f0, ios 0x1650e8;
|
||||
static cocos2d::CCArray* create() = mac 0x419cb0, ios 0x164ec8;
|
||||
static auto createWithObject(cocos2d::CCObject*) = mac 0x419d50;
|
||||
auto fastRemoveObject(cocos2d::CCObject*) = mac 0x41a520;
|
||||
auto fastRemoveObjectAtIndex(unsigned int) = mac 0x41a500;
|
||||
// auto addObjectsFromArray(cocos2d::CCArray*) = mac 0x41a2d0;
|
||||
// auto containsObject(cocos2d::CCObject*) const = mac 0x41a3e0;
|
||||
// auto count() const = mac 0x41a2f0, ios 0x1650e8;
|
||||
// static cocos2d::CCArray* create() = mac 0x419cb0, ios 0x164ec8;
|
||||
// static auto createWithObject(cocos2d::CCObject*) = mac 0x419d50;
|
||||
// auto fastRemoveObject(cocos2d::CCObject*) = mac 0x41a520;
|
||||
// auto fastRemoveObjectAtIndex(unsigned int) = mac 0x41a500;
|
||||
auto fastRemoveObjectAtIndexNew(unsigned int) = mac 0x41a510;
|
||||
auto insertObject(cocos2d::CCObject*, unsigned int) = mac 0x41a460;
|
||||
auto lastObject() = mac 0x41a360;
|
||||
auto objectAtIndex(unsigned int) = mac 0x41a340, ios 0x16510c;
|
||||
auto removeAllObjects() = mac 0x41a4f0, ios 0x1651f0;
|
||||
auto removeLastObject(bool) = mac 0x41a470;
|
||||
auto removeObject(cocos2d::CCObject*, bool) = mac 0x41a490;
|
||||
auto removeObjectAtIndex(unsigned int, bool) = mac 0x41a4b0;
|
||||
auto stringAtIndex(unsigned int) = mac 0x41a320;
|
||||
// auto insertObject(cocos2d::CCObject*, unsigned int) = mac 0x41a460;
|
||||
// auto lastObject() = mac 0x41a360;
|
||||
// auto objectAtIndex(unsigned int) = mac 0x41a340, ios 0x16510c;
|
||||
// auto removeAllObjects() = mac 0x41a4f0, ios 0x1651f0;
|
||||
// auto removeLastObject(bool) = mac 0x41a470;
|
||||
// auto removeObject(cocos2d::CCObject*, bool) = mac 0x41a490;
|
||||
// auto removeObjectAtIndex(unsigned int, bool) = mac 0x41a4b0;
|
||||
// auto stringAtIndex(unsigned int) = mac 0x41a320;
|
||||
}
|
||||
|
||||
class cocos2d::CCBezierTo {
|
||||
|
|
|
@ -483,6 +483,7 @@ class CCScrollLayerExt : cocos2d::CCLayer {
|
|||
void moveToTopWithOffset(float) = mac 0x2357d0, win 0x1b420;
|
||||
CCScrollLayerExt(cocos2d::CCRect rect) = mac 0x235130, win 0x1b020, ios 0x21f05c;
|
||||
void scrollLayer(float scroll) = mac 0x236490, win 0x1be20;
|
||||
void updateIndicators(float unknown) = win 0x1b710;
|
||||
|
||||
cocos2d::CCTouch* m_touch;
|
||||
cocos2d::CCPoint m_touchPosition;
|
||||
|
@ -1204,7 +1205,7 @@ class EditorUI : cocos2d::CCLayer, FLAlertLayerProtocol, ColorSelectDelegate, GJ
|
|||
cocos2d::CCPoint getTouchPoint(cocos2d::CCTouch* touch, cocos2d::CCEvent* event) = win 0x90620;
|
||||
void onSelectBuildTab(cocos2d::CCObject* sender) = win 0x887f0;
|
||||
void onCreateButton(cocos2d::CCObject* sender) = win 0x854f0;
|
||||
CCMenuItemSpriteExtra* getSpriteButton(const char* sprite, cocos2d::SEL_MenuHandler callback, cocos2d::CCMenu* menu, float scale) = win 0x78bf0;
|
||||
CCMenuItemSpriteExtra* getSpriteButton(const char* sprite, cocos2d::SEL_MenuHandler callback, cocos2d::CCMenu* menu, float scale) = mac 0xb500, win 0x78bf0;
|
||||
cocos2d::CCPoint offsetForKey(int objID) = win 0x92310;
|
||||
void updateDeleteMenu() = win 0x7c5d0;
|
||||
void updateCreateMenu(bool updateTab) = mac 0x1e960, win 0x85530;
|
||||
|
@ -1257,6 +1258,7 @@ class EditorUI : cocos2d::CCLayer, FLAlertLayerProtocol, ColorSelectDelegate, GJ
|
|||
void editColor(cocos2d::CCObject* sender) = mac 0x19190, win 0x8d3c0;
|
||||
void alignObjects(cocos2d::CCArray* objs, bool alignY) = win 0x8f320;
|
||||
virtual void scrollWheel(float vertical, float horizontal) = win 0x921d0, mac 0x31370, ios 0x2c4884;
|
||||
void createMoveMenu() = mac 0x275e0, win 0x8c0d0;
|
||||
|
||||
EditButtonBar* m_buttonBar;
|
||||
PAD = mac 0x8, win 0x4;
|
||||
|
@ -1514,9 +1516,9 @@ class FLAlertLayer : cocos2d::CCLayerColor {
|
|||
bool scrollable,
|
||||
float height
|
||||
) = mac 0x25e1b0, win 0x228e0;
|
||||
static FLAlertLayer* create(FLAlertLayerProtocol*, char const*, gd::string, char const*, char const*) = mac 0x25de00, win 0x22680;
|
||||
static FLAlertLayer* create(FLAlertLayerProtocol*, char const*, gd::string, char const*, char const*, float) = mac 0x25e0e0, win 0x22730, ios 0x1fe374;
|
||||
static FLAlertLayer* create(FLAlertLayerProtocol*, char const*, gd::string, char const*, char const*, float, bool, float) = mac 0x25dec0, win 0x227e0;
|
||||
static FLAlertLayer* create(FLAlertLayerProtocol* protocol, char const* title, gd::string content, char const* btn1, char const* btn2) = mac 0x25de00, win 0x22680;
|
||||
static FLAlertLayer* create(FLAlertLayerProtocol* protocol, char const* title, gd::string content, char const* btn1, char const* btn2, float width) = mac 0x25e0e0, win 0x22730, ios 0x1fe374;
|
||||
static FLAlertLayer* create(FLAlertLayerProtocol* protocol, char const* title, gd::string content, char const* btn1, char const* btn2, float width, bool scrollable, float height) = mac 0x25dec0, win 0x227e0;
|
||||
void onBtn1(cocos2d::CCObject*) = mac 0x25ec20, win 0x23340;
|
||||
void onBtn2(cocos2d::CCObject*) = mac 0x25ec80, win 0x23380;
|
||||
|
||||
|
@ -2025,7 +2027,9 @@ class GJEffectManager : cocos2d::CCNode {
|
|||
void stopActionsForTrigger(EffectGameObject*) = mac 0x183150;
|
||||
void stopMoveActionsForGroup(int) = mac 0x1830e0;
|
||||
void storeTriggeredID(int) = mac 0x185380;
|
||||
void toggleGroup(int, bool) = mac 0x182c80;
|
||||
void toggleGroup(int item, bool value) { // mac 0x182c80;
|
||||
m_groupToggled[item] = value;
|
||||
}
|
||||
void traverseInheritanceChain(InheritanceNode*) = mac 0x181850, win 0x11caf0;
|
||||
void updateActiveOpacityEffects() = mac 0x1847e0;
|
||||
void updateColorAction(ColorAction*) = mac 0x184560;
|
||||
|
@ -2897,7 +2901,9 @@ class GameManager : GManager {
|
|||
bool m_likedFacebook;
|
||||
bool m_followedTwitter;
|
||||
bool m_subbedYoutube;
|
||||
int m_unknownInt;
|
||||
// there are 4 bytes too many between m_timeOffset and m_playerFrameRand1
|
||||
// and i'm guessing it's this one
|
||||
// int m_unknownInt;
|
||||
double m_socialsDuration;
|
||||
bool m_showedAd;
|
||||
bool m_unknownBool;
|
||||
|
@ -3786,7 +3792,7 @@ class LevelEditorLayer : GJBaseGameLayer, LevelSettingsDelegate {
|
|||
|
||||
class LevelInfoLayer : cocos2d::CCLayer, LevelDownloadDelegate, LevelUpdateDelegate, RateLevelDelegate, LikeItemDelegate, FLAlertLayerProtocol, LevelDeleteDelegate, NumberInputDelegate, SetIDPopupDelegate {
|
||||
static LevelInfoLayer* create(GJGameLevel* level) = mac 0x15f290, win 0x175d50;
|
||||
bool init(GJGameLevel* level) = win 0x175DF0;
|
||||
bool init(GJGameLevel* level) = win 0x175df0, mac 0x15f520;
|
||||
void onGarage(cocos2d::CCObject* sender) = win 0x177c10;
|
||||
void onViewProfile(cocos2d::CCObject* sender) = win 0x17ac90;
|
||||
void onLevelInfo(cocos2d::CCObject* sender) = win 0x17acf0;
|
||||
|
@ -4007,7 +4013,7 @@ class MenuLayer : cocos2d::CCLayer, FLAlertLayerProtocol, GooglePlayDelegate {
|
|||
void onTwitter(cocos2d::CCObject*) = win 0x191980;
|
||||
void onYouTube(cocos2d::CCObject*) = win 0x1919A0;
|
||||
static cocos2d::CCScene* scene(bool) = mac 0x1d12d0, win 0x190720, ios 0x19e57c;
|
||||
MenuLayer* node() = win 0x190550;
|
||||
static MenuLayer* node() = win 0x190550;
|
||||
|
||||
cocos2d::CCSprite* m_googlePlaySprite;
|
||||
cocos2d::CCSprite* m_viewProfileInfoText;
|
||||
|
@ -5212,18 +5218,22 @@ class TableView : CCScrollLayerExt, CCScrollLayerExtDelegate {
|
|||
static TableView* create(TableViewDelegate*, TableViewDataSource*, cocos2d::CCRect) = mac 0x37eb30, win 0x30ed0;
|
||||
void reloadData() = mac 0x37f970, win 0x317e0;
|
||||
|
||||
virtual void onEnter() = mac 0x37ff30, ios 0x21dcac;
|
||||
virtual void onExit() = mac 0x37ff40, ios 0x21dcb0;
|
||||
virtual void onEnter() {
|
||||
CCLayer::onEnter();
|
||||
}
|
||||
virtual void onExit() {
|
||||
CCLayer::onExit();
|
||||
}
|
||||
virtual bool ccTouchBegan(cocos2d::CCTouch*, cocos2d::CCEvent*) = mac 0x380120, ios 0x21de24, win 0x31de0;
|
||||
virtual void ccTouchMoved(cocos2d::CCTouch*, cocos2d::CCEvent*) = mac 0x380be0, ios 0x21e5e8;
|
||||
virtual void ccTouchEnded(cocos2d::CCTouch*, cocos2d::CCEvent*) = mac 0x3809a0, ios 0x21e46c;
|
||||
virtual void ccTouchCancelled(cocos2d::CCTouch*, cocos2d::CCEvent*) = mac 0x380b20, ios 0x21e580;
|
||||
virtual void registerWithTouchDispatcher() = mac 0x37ff50, ios 0x21dcb4;
|
||||
virtual void scrollWheel(float, float) = mac 0x380cd0, ios 0x21e6b4;
|
||||
virtual void scrllViewWillBeginDecelerating(CCScrollLayerExt*) = mac 0x3818a0, ios 0x21efd4;
|
||||
virtual void scrollViewDidEndDecelerating(CCScrollLayerExt*) = mac 0x3818c0, ios 0x21efdc;
|
||||
virtual void scrollViewTouchMoving(CCScrollLayerExt*) = mac 0x3818e0, ios 0x21efe4;
|
||||
virtual void scrollViewDidEndMoving(CCScrollLayerExt*) = mac 0x381900, ios 0x21efec;
|
||||
virtual void ccTouchMoved(cocos2d::CCTouch*, cocos2d::CCEvent*) = mac 0x380be0, ios 0x21e5e8, win 0x31f30;
|
||||
virtual void ccTouchEnded(cocos2d::CCTouch*, cocos2d::CCEvent*) = mac 0x3809a0, ios 0x21e46c, win 0x31e80;
|
||||
virtual void ccTouchCancelled(cocos2d::CCTouch*, cocos2d::CCEvent*) = mac 0x380b20, ios 0x21e580, win 0x31ed0;
|
||||
virtual void registerWithTouchDispatcher() = mac 0x37ff50, ios 0x21dcb4, win 0x12aa0;
|
||||
virtual void scrollWheel(float, float) = mac 0x380cd0, ios 0x21e6b4, win 0x320a0;
|
||||
virtual void scrllViewWillBeginDecelerating(CCScrollLayerExt*) {}
|
||||
virtual void scrollViewDidEndDecelerating(CCScrollLayerExt*) {}
|
||||
virtual void scrollViewTouchMoving(CCScrollLayerExt*) {}
|
||||
virtual void scrollViewDidEndMoving(CCScrollLayerExt*) {}
|
||||
|
||||
bool m_touchOutOfBoundary;
|
||||
cocos2d::CCTouch* m_touchStart;
|
||||
|
@ -5308,7 +5318,7 @@ class TextArea : cocos2d::CCSprite {
|
|||
virtual void draw() {}
|
||||
virtual void setOpacity(unsigned char) = mac 0x19f760, win 0x33800;
|
||||
bool init(gd::string str, char const* font, float width, float height, cocos2d::CCPoint anchor, float scale, bool disableColor) = mac 0x19ec70, win 0x33370, ios 0x92444;
|
||||
static TextArea* create(gd::string str, char const* font, float scale, float width, cocos2d::CCPoint anchor, float height, bool disableColor) = mac 0x19eb40, win 0x33270;
|
||||
static TextArea* create(gd::string str, char const* font, float width, float height, cocos2d::CCPoint anchor, float scale, bool disableColor) = mac 0x19eb40, win 0x33270;
|
||||
void colorAllCharactersTo(cocos2d::ccColor3B color) = win 0x33830;
|
||||
void setString(gd::string str) = mac 0x19eda0, win 0x33480;
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@ project(Codegen LANGUAGES C CXX)
|
|||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
add_subdirectory(Broma)
|
||||
add_subdirectory(../fmt ${CMAKE_CURRENT_BINARY_DIR}/fmt)
|
||||
add_subdirectory(../filesystem ${CMAKE_CURRENT_BINARY_DIR}/fs)
|
||||
add_subdirectory(../loader/include/Geode/external/fmt ${CMAKE_CURRENT_BINARY_DIR}/fmt)
|
||||
add_subdirectory(../loader/include/Geode/external/filesystem ${CMAKE_CURRENT_BINARY_DIR}/fs)
|
||||
|
||||
file(GLOB SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp
|
||||
|
|
|
@ -35,6 +35,7 @@ namespace geode::modifier {{
|
|||
using Base = {class_name};
|
||||
static void apply() {{
|
||||
using namespace geode::core::meta;
|
||||
|
||||
)GEN";
|
||||
|
||||
// requires: index, class_name, arg_types, function_name, raw_arg_types, non_virtual
|
||||
|
|
|
@ -1,197 +0,0 @@
|
|||
# History of Interface Classes
|
||||
|
||||
### 1a07998694824abc492eb6b9d98591d0c0dc26e5
|
||||
This version had the problem that you could only hook a single class inside a mod container, and it only supported virtual functions
|
||||
Also the first version of the interface / cackit classes
|
||||
```cpp
|
||||
class: public $EditorUI {
|
||||
void undoLastAction() override {
|
||||
std::cout << "We have " << cac_this->getSelectedObjects()->count() << " objects elected\n";
|
||||
$EditorUI::undoLastAction();
|
||||
}
|
||||
} MyEditorUIHook;
|
||||
```
|
||||
|
||||
### 781465559ec779e295d1b25a511bbe1d277dd702
|
||||
This version allowed for multiple classes, though the classes still needed to be inside the same source file and between the two macros `CAC_HOOKS` and `END_CAC_HOOKS`
|
||||
My personal second least favorite
|
||||
```cpp
|
||||
CAC_HOOKS
|
||||
class: public $EditorUI {
|
||||
void undoLastAction() override {
|
||||
std::cout << "Undo!\n";
|
||||
}
|
||||
} MyEditorUIHook;
|
||||
END_CAC_HOOKS
|
||||
```
|
||||
|
||||
### e577a57317681332d4974e1e299159c2f6e307af
|
||||
This version is the first one that utilized the CRTP system, which eventually became the heart of the interface classes
|
||||
```cpp
|
||||
CAC_HOOKS
|
||||
class EditorUIHook: public $EditorUI<EditorUIHook> {
|
||||
void undoLastAction() override {
|
||||
std::cout << "Undo!\n";
|
||||
}
|
||||
} MyEditorUIHook;
|
||||
END_CAC_HOOKS
|
||||
```
|
||||
|
||||
### 4c10edc67ac8893136dbc97df30fe04996d69001
|
||||
This version ditched the the macros that put the hooks inside an anonymous function for a static global variable approach. `APPLY_HOOKS` macro is exactly that.
|
||||
```cpp
|
||||
class EditorUIHook: public $EditorUI<EditorUIHook> {
|
||||
public:
|
||||
void undoLastAction() override {
|
||||
std::cout << "Undo!\n";
|
||||
$EditorUI::undoLastAction();
|
||||
}
|
||||
} MyEditorUIHook;
|
||||
|
||||
APPLY_HOOKS();
|
||||
```
|
||||
|
||||
### c9f090d539b6b74742f2bab793c4cc88991f981a
|
||||
This version removed the CRTP system, not needing to get the address of the virtual with the derived
|
||||
```cpp
|
||||
class: public $EditorUI {
|
||||
public:
|
||||
void undoLastAction() override {
|
||||
std::cout << "Undo!\n";
|
||||
$EditorUI::undoLastAction();
|
||||
}
|
||||
} MyEditorUIHook;
|
||||
|
||||
APPLY_HOOKS();
|
||||
```
|
||||
|
||||
### 37c7ec8df248a02254de6d84daecca444a484384
|
||||
This version removed the need for the public storage access, for the same reason as above
|
||||
```cpp
|
||||
class: public $EditorUI {
|
||||
void undoLastAction() override {
|
||||
std::cout << "Undo!\n";
|
||||
$EditorUI::undoLastAction();
|
||||
}
|
||||
} MyEditorUIHook;
|
||||
|
||||
APPLY_HOOKS();
|
||||
```
|
||||
|
||||
### de5eee71b18aa50c225a76667861610049c00b21
|
||||
This version brang back both CRTP system (but this time wrapped inside a macro) and the public access. Now it also supported all types of functions, and not just virtual functions
|
||||
```cpp
|
||||
class REDIRECT($EditorUI) {
|
||||
public:
|
||||
void undoLastAction() {
|
||||
std::cout << "Undo!\n";
|
||||
$EditorUI::undoLastAction();
|
||||
}
|
||||
} MyEditorUIHook;
|
||||
|
||||
APPLY_HOOKS();
|
||||
```
|
||||
|
||||
### f18c2f73ae1e1cc1662dbcbe54f36e657a699723
|
||||
This version renamed the macros to the more Geode familiar syntax with the $ prefixes
|
||||
```cpp
|
||||
class $redirect(EditorUI) {
|
||||
public:
|
||||
void undoLastAction() {
|
||||
std::cout << "Undo!\n";
|
||||
$EditorUI::undoLastAction();
|
||||
}
|
||||
} MyEditorUIHook;
|
||||
|
||||
$apply();
|
||||
```
|
||||
|
||||
### 4027f1e82a1461fad30ef6e51b6dfc1b887479a8
|
||||
This version ditched redirect for implement because I was dumb and I misinterpreted something and all
|
||||
IIRC it was related to the constructors
|
||||
My personal least favorite
|
||||
```cpp
|
||||
class $implement(EditorUI, MyEditorUIHook) {
|
||||
public:
|
||||
void undoLastAction(CCObject* p0) {
|
||||
std::cout << "Undo!" << std::endl;
|
||||
$EditorUI::undoLastAction(p0);
|
||||
}
|
||||
} endImplement(MyEditorUIHook);
|
||||
|
||||
$apply();
|
||||
```
|
||||
|
||||
### b32b9f0783b9079269685260ca7188d557f9307e
|
||||
Thankfully this version reverted that while fixing the problem too
|
||||
```cpp
|
||||
class $redirect(EditorUI) {
|
||||
public:
|
||||
void undoLastAction() {
|
||||
std::cout << "Undo!\n";
|
||||
$EditorUI::undoLastAction();
|
||||
}
|
||||
} MyEditorUIHook;
|
||||
|
||||
$apply();
|
||||
```
|
||||
|
||||
### 7531b2ae915447df8eb9ce825ee7755303396812
|
||||
This version removed the need for the `$apply` macro
|
||||
```cpp
|
||||
class $redirect(EditorUI) {
|
||||
public:
|
||||
void undoLastAction() {
|
||||
std::cout << "Undo!\n";
|
||||
$EditorUI::undoLastAction();
|
||||
}
|
||||
} MyEditorUIHook;
|
||||
```
|
||||
|
||||
### e6ec14774b94f8b5cdc30a246ed48d46674bce95
|
||||
This version removed the need for both the variable initializer and the public specifier, using some macro stuff
|
||||
My personal second favorite
|
||||
```cpp
|
||||
class $redirect(EditorUI) {
|
||||
void undoLastAction() {
|
||||
std::cout << "Undo!\n";
|
||||
$EditorUI::undoLastAction();
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### f361adca95c6e3c07e0fde654fd7c8c1a59d3b2f
|
||||
This version combined the two macros to create the ultimate macro `$`
|
||||
My personal favorite
|
||||
```cpp
|
||||
class $(EditorUI) {
|
||||
void undoLastAction() {
|
||||
std::cout << "Undo!\n";
|
||||
$EditorUI::undoLastAction();
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### de74c1ffa4a3a7f72ac2394fbfb4a1262fbe470b
|
||||
This version allowed for the creation of fields, which let you effectively add extra fields to classes
|
||||
You can access them with the special c++ operator ->*
|
||||
```cpp
|
||||
class $(EditorUI) {
|
||||
member_t<int> number_of_undos;
|
||||
void undoLastAction() {
|
||||
std::cout << "You have pressed undo " << ++this->*number_of_undos << " times!\n";
|
||||
$EditorUI::undoLastAction();
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### 5f5bead640bc2a52c087f41c49c3354073809f46
|
||||
This version added the ability to use the `$orig` macro to call the original function, instead of needing to type it out manually.
|
||||
```cpp
|
||||
class $(EditorUI) {
|
||||
void undoLastAction() {
|
||||
std::cout << "Undo!\n";
|
||||
$orig();
|
||||
}
|
||||
};
|
||||
```
|
|
@ -10,22 +10,21 @@ file(READ resources/about.md LOADER_ABOUT_MD)
|
|||
configure_file(src/internal/about.hpp.in ${CMAKE_CURRENT_SOURCE_DIR}/src/internal/about.hpp)
|
||||
|
||||
# Source files
|
||||
file(GLOB CORE_SOURCES
|
||||
file(GLOB SOURCES CONFIGURE_DEPENDS
|
||||
src/cocos2d-ext/*.cpp
|
||||
src/cocos2d-ext/zip/*.cpp
|
||||
src/core/*.cpp
|
||||
src/hooks/*.cpp
|
||||
src/ids/*.cpp
|
||||
src/internal/*.cpp
|
||||
src/internal/windows/*.cpp
|
||||
src/internal/mac/*.cpp
|
||||
src/internal/ios/*.cpp
|
||||
src/platform/mac/*.cpp
|
||||
src/platform/ios/*.cpp
|
||||
src/load/*.cpp
|
||||
src/load/windows/*.cpp
|
||||
src/load/mac/*.cpp
|
||||
src/mac/*.cpp
|
||||
src/main.cpp
|
||||
src/utils/*.cpp
|
||||
src/utils/windows/*.cpp
|
||||
src/utils/zip/*.cpp
|
||||
src/index/*.cpp
|
||||
src/ui/nodes/*.cpp
|
||||
src/ui/internal/*.cpp
|
||||
|
@ -36,25 +35,50 @@ file(GLOB CORE_SOURCES
|
|||
src/ui/internal/settings/*.cpp
|
||||
)
|
||||
|
||||
# Obj-c sources
|
||||
file(GLOB OBJC_SOURCES
|
||||
src/internal/ios/*.mm
|
||||
src/internal/mac/*.mm
|
||||
src/platform/ios/*.mm
|
||||
src/platform/mac/*.mm
|
||||
src/load/ios/*.mm
|
||||
src/load/mac/*.mm
|
||||
src/utils/ios/*.mm
|
||||
src/utils/mac/*.mm
|
||||
)
|
||||
set_source_files_properties(${OBJC_SOURCES} PROPERTIES SKIP_PRECOMPILE_HEADERS ON)
|
||||
|
||||
# Add platform sources
|
||||
if (WIN32)
|
||||
|
||||
file(GLOB WIN_SOURCES CONFIGURE_DEPENDS
|
||||
src/platform/windows/*.cpp
|
||||
)
|
||||
list(APPEND SOURCES ${WIN_SOURCES})
|
||||
|
||||
elseif(IOS)
|
||||
|
||||
file(GLOB IOS_SOURCES CONFIGURE_DEPENDS
|
||||
src/platform/ios/*.cpp
|
||||
)
|
||||
list(APPEND SOURCES ${IOS_SOURCES})
|
||||
list(APPEND SOURCES ${OBJC_SOURCES})
|
||||
|
||||
elseif(APPLE)
|
||||
|
||||
file(GLOB MAC_SOURCES CONFIGURE_DEPENDS
|
||||
src/platform/mac/*.cpp
|
||||
)
|
||||
list(APPEND SOURCES ${MAC_SOURCES})
|
||||
list(APPEND SOURCES ${OBJC_SOURCES})
|
||||
|
||||
endif()
|
||||
|
||||
# Embed version info in binary
|
||||
if (WIN32)
|
||||
configure_file(src/internal/windows/info.rc.in info.rc)
|
||||
set(CORE_SOURCES ${CORE_SOURCES} ${CMAKE_CURRENT_BINARY_DIR}/info.rc)
|
||||
configure_file(src/platform/windows/info.rc.in info.rc)
|
||||
set(SOURCES ${SOURCES} ${CMAKE_CURRENT_BINARY_DIR}/info.rc)
|
||||
endif()
|
||||
|
||||
add_library(${PROJECT_NAME} SHARED
|
||||
${CORE_SOURCES}
|
||||
${OBJC_SOURCES}
|
||||
)
|
||||
add_library(${PROJECT_NAME} SHARED ${SOURCES})
|
||||
|
||||
make_directory("${GEODE_BIN_PATH}/nightly")
|
||||
|
||||
|
@ -113,7 +137,6 @@ add_subdirectory(lilac)
|
|||
target_link_libraries(${PROJECT_NAME} z lilac_hook geode-sdk)
|
||||
|
||||
# Use precompiled headers for faster builds
|
||||
set_source_files_properties(${OBJC_SOURCES} PROPERTIES SKIP_PRECOMPILE_HEADERS ON)
|
||||
target_precompile_headers(${PROJECT_NAME} PRIVATE
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/DefaultInclude.hpp"
|
||||
# "${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/Utils.hpp"
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
#include "loader/cgeode.h"
|
|
@ -1,15 +1,19 @@
|
|||
#pragma once
|
||||
|
||||
#include "ui/BasedButton.hpp"
|
||||
#include "ui/ColorPickPopup.hpp"
|
||||
#include "ui/EnterLayerEvent.hpp"
|
||||
#include "ui/BasedButtonSprite.hpp"
|
||||
#include "ui/IconButtonSprite.hpp"
|
||||
#include "ui/InputNode.hpp"
|
||||
#include "ui/LayerBG.hpp"
|
||||
#include "ui/ListView.hpp"
|
||||
#include "ui/MDPopup.hpp"
|
||||
#include "ui/MDTextArea.hpp"
|
||||
#include "ui/Notification.hpp"
|
||||
#include "ui/Popup.hpp"
|
||||
#include "ui/SceneManager.hpp"
|
||||
#include "ui/ScrollLayer.hpp"
|
||||
#include "ui/SelectList.hpp"
|
||||
#include "ui/Scrollbar.hpp"
|
||||
#include "ui/TextRenderer.hpp"
|
||||
|
|
|
@ -1,17 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
#include "utils/Ref.hpp"
|
||||
#include "DefaultInclude.hpp"
|
||||
#include "utils/Result.hpp"
|
||||
#include "utils/VersionInfo.hpp"
|
||||
#include "utils/casts.hpp"
|
||||
#include "utils/cocos.hpp"
|
||||
#include "utils/convert.hpp"
|
||||
#include "utils/ext.hpp"
|
||||
#include "utils/map.hpp"
|
||||
#include "utils/string.hpp"
|
||||
#include "utils/file.hpp"
|
||||
#include "utils/general.hpp"
|
||||
#include "utils/json.hpp"
|
||||
#include "utils/operators.hpp"
|
||||
#include "utils/platform.hpp"
|
||||
#include "utils/timer.hpp"
|
||||
#include "utils/types.hpp"
|
||||
|
||||
#include <Geode/DefaultInclude.hpp>
|
||||
|
|
|
@ -330,6 +330,14 @@ namespace gd {
|
|||
m_capacity_end = m_start + input.size();
|
||||
std::copy(input.begin(), input.end(), tmp);
|
||||
}
|
||||
|
||||
void clear() {
|
||||
delete[] m_start;
|
||||
auto tmp = new T[0];
|
||||
m_start = tmp;
|
||||
m_finish = m_start;
|
||||
m_capacity_end = m_start;
|
||||
}
|
||||
|
||||
T& front() {
|
||||
return *m_start;
|
||||
|
@ -448,12 +456,12 @@ namespace gd {
|
|||
}
|
||||
}
|
||||
|
||||
operator std::vector<bool>() {
|
||||
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;
|
||||
}
|
||||
|
||||
operator std::vector<bool>() const {
|
||||
|
@ -464,12 +472,14 @@ namespace gd {
|
|||
return out;
|
||||
}
|
||||
|
||||
vector(vector<bool> const& lol) : vector(std::vector<bool>(lol)) {}
|
||||
_bit_reference operator[](size_t index) {
|
||||
const auto real_index = index / sizeof(uintptr_t);
|
||||
const auto offset = index % sizeof(uintptr_t);
|
||||
return _bit_reference(&m_start.m_bitptr[real_index], 1UL << offset);
|
||||
}
|
||||
|
||||
vector() : vector(std::vector<bool>()) {}
|
||||
|
||||
~vector() {
|
||||
delete[] m_start.m_bitptr;
|
||||
bool operator[](size_t index) const {
|
||||
return const_cast<vector&>(*this)[index];
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
|
@ -37,6 +37,8 @@
|
|||
#include "../kazmath/include/kazmath/kazmath.h"
|
||||
#include "../script_support/CCScriptSupport.h"
|
||||
#include "../include/CCProtocols.h"
|
||||
#include "Layout.hpp"
|
||||
#include <any>
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
|
@ -847,6 +849,7 @@ public:
|
|||
friend class geode::modifier::FieldContainer;
|
||||
|
||||
geode::modifier::FieldContainer* getFieldContainer();
|
||||
std::optional<std::any> getAttributeInternal(std::string const& attribute);
|
||||
|
||||
public:
|
||||
/**
|
||||
|
@ -858,7 +861,8 @@ public:
|
|||
* Set the string ID of this node. String IDs are a Geode addition
|
||||
* that are much safer to use to get nodes than absolute indexes
|
||||
* @param id The ID of the node, recommended to be in kebab case
|
||||
* without any spaces or uppercase letters
|
||||
* without any spaces or uppercase letters. If the node is added
|
||||
* by a mod, use the _spr literal to append the mod ID to it
|
||||
*/
|
||||
void setID(std::string const& id);
|
||||
|
||||
|
@ -875,6 +879,28 @@ public:
|
|||
* @returns The child, or nullptr if none was found
|
||||
*/
|
||||
CCNode* getChildByIDRecursive(std::string const& id);
|
||||
|
||||
void setAttribute(std::string const& attribute, std::any value);
|
||||
template<class T>
|
||||
std::optional<T> getAttribute(std::string const& attribute) {
|
||||
if (auto value = this->getAttributeInternal(attribute)) {
|
||||
try {
|
||||
return std::any_cast<T>(value.value());
|
||||
} catch(...) {
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void setLayout(Layout* layout, bool apply = true);
|
||||
Layout* getLayout();
|
||||
void updateLayout();
|
||||
|
||||
void setPositionHint(PositionHint hint);
|
||||
PositionHint getPositionHint();
|
||||
|
||||
void swapChildIndices(CCNode* first, CCNode* second);
|
||||
);
|
||||
|
||||
/// @{
|
||||
|
|
153
loader/include/Geode/cocos/base_nodes/Layout.hpp
Normal file
153
loader/include/Geode/cocos/base_nodes/Layout.hpp
Normal file
|
@ -0,0 +1,153 @@
|
|||
#pragma once
|
||||
|
||||
#include "../include/ccMacros.h"
|
||||
#include "../cocoa/CCAffineTransform.h"
|
||||
#include "../cocoa/CCArray.h"
|
||||
#include <Geode/platform/platform.hpp>
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
class CCNode;
|
||||
|
||||
/**
|
||||
* Layouts automatically handle the positioning of nodes. Use CCNode::setLayout
|
||||
* to apply a layout to a node, and then use CCNode::updateLayout to apply
|
||||
* the layout's positioning. Geode comes with a few default layouts like
|
||||
* RowLayout, ColumnLayout, and GridLayout, but if you need a different kind
|
||||
* of layout you can inherit from the Layout class.
|
||||
*/
|
||||
class Layout {
|
||||
public:
|
||||
/**
|
||||
* Automatically apply the layout's positioning on a set of nodes
|
||||
* @param nodes Nodes to position
|
||||
* @param availableSize Give hints to the layout about how much space is
|
||||
* available. Note that the layout may still overflow
|
||||
*/
|
||||
virtual void apply(CCArray* nodes, CCSize const& availableSize) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines how a node should be positioned within its parent, if that
|
||||
* parent has an automatically positioning layout
|
||||
*/
|
||||
enum class PositionHint {
|
||||
// The container can determine the best position
|
||||
// for this node
|
||||
Default,
|
||||
// The container's layout should not affect the
|
||||
// position of this node
|
||||
Absolute,
|
||||
};
|
||||
|
||||
/**
|
||||
* Specifies the alignment of something
|
||||
*/
|
||||
enum class Alignment {
|
||||
Begin,
|
||||
Center,
|
||||
End,
|
||||
};
|
||||
|
||||
/**
|
||||
* Simple layout for arranging nodes in a row (horizontal line)
|
||||
*/
|
||||
class GEODE_DLL RowLayout : public Layout {
|
||||
protected:
|
||||
Alignment m_alignment = Alignment::Center;
|
||||
std::optional<float> m_alignVertically;
|
||||
float m_gap;
|
||||
|
||||
public:
|
||||
void apply(CCArray* nodes, CCSize const& availableSize) override;
|
||||
|
||||
/**
|
||||
* Create a new RowLayout. Note that this class is not automatically
|
||||
* managed by default, so you must assign it to a CCNode or manually
|
||||
* manage the memory yourself.
|
||||
* @param gap Space between nodes
|
||||
* @param alignVertically Whether to align the nodes vertically, and if so,
|
||||
* what Y position to align them at
|
||||
* @returns Created RowLayout
|
||||
*/
|
||||
static RowLayout* create(
|
||||
float gap = 5.f,
|
||||
std::optional<float> alignVertically = std::nullopt
|
||||
);
|
||||
|
||||
RowLayout* setAlignment(Alignment align);
|
||||
RowLayout* setGap(float gap);
|
||||
RowLayout* setAlignVertically(std::optional<float> align);
|
||||
};
|
||||
|
||||
/**
|
||||
* Simple layout for arranging nodes in a column (vertical line)
|
||||
*/
|
||||
class GEODE_DLL ColumnLayout : public Layout {
|
||||
protected:
|
||||
Alignment m_alignment = Alignment::Center;
|
||||
std::optional<float> m_alignHorizontally;
|
||||
float m_gap;
|
||||
|
||||
public:
|
||||
void apply(CCArray* nodes, CCSize const& availableSize) override;
|
||||
|
||||
static ColumnLayout* create(
|
||||
float gap = 5.f,
|
||||
std::optional<float> alignHorizontally = std::nullopt
|
||||
);
|
||||
|
||||
ColumnLayout* setAlignment(Alignment align);
|
||||
ColumnLayout* setGap(float gap);
|
||||
ColumnLayout* setAlignHorizontally(std::optional<float> align);
|
||||
};
|
||||
|
||||
/**
|
||||
* Grid direction; which direction the grid should add its next row to if the
|
||||
* current row is full
|
||||
*/
|
||||
enum class GridDirection {
|
||||
// Downward
|
||||
Column,
|
||||
// Upward
|
||||
ReverseColumn,
|
||||
// Right
|
||||
Row,
|
||||
// Left
|
||||
ReverseRow,
|
||||
};
|
||||
|
||||
/**
|
||||
* Grid alignment; same as normal Alignment but also features the "Stretch"
|
||||
* option which will stretch the row out to be the same size as the others
|
||||
*/
|
||||
enum class GridAlignment {
|
||||
Begin,
|
||||
Center,
|
||||
Stretch,
|
||||
End,
|
||||
};
|
||||
|
||||
class GEODE_DLL GridLayout : public Layout {
|
||||
protected:
|
||||
GridDirection m_direction = GridDirection::Column;
|
||||
GridAlignment m_alignment = GridAlignment::Center;
|
||||
std::optional<size_t> m_rowSize;
|
||||
|
||||
public:
|
||||
void apply(CCArray* nodes, CCSize const& availableSize) override;
|
||||
|
||||
static GridLayout* create(
|
||||
std::optional<size_t> rowSize,
|
||||
GridAlignment alignment = GridAlignment::Center,
|
||||
GridDirection direction = GridDirection::Column
|
||||
);
|
||||
|
||||
GridLayout* setDirection(GridDirection direction);
|
||||
GridLayout* setAlignment(GridAlignment alignment);
|
||||
GridLayout* setRowSize(std::optional<size_t> rowSize);
|
||||
};
|
||||
|
||||
NS_CC_END
|
|
@ -152,6 +152,9 @@ public:
|
|||
* @js getInstance
|
||||
*/
|
||||
static CCSpriteFrameCache* sharedSpriteFrameCache(void);
|
||||
GEODE_ADD(
|
||||
static CCSpriteFrameCache* get();
|
||||
);
|
||||
|
||||
/** Purges the cache. It releases all the Sprite Frames and the retained instance. */
|
||||
static void purgeSharedSpriteFrameCache(void);
|
||||
|
|
|
@ -91,6 +91,9 @@ public:
|
|||
* @js getInstance
|
||||
*/
|
||||
static CCTextureCache * sharedTextureCache();
|
||||
GEODE_ADD(
|
||||
static CCTextureCache* get();
|
||||
);
|
||||
|
||||
/** purges the cache. It releases the retained instance.
|
||||
@since v0.99.0
|
||||
|
|
|
@ -47,7 +47,7 @@ namespace geode::core {
|
|||
|
||||
inline Result<> remove(HookHandle const& handle) {
|
||||
impl::removeHook(handle);
|
||||
return Ok<>();
|
||||
return Ok();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,6 +19,7 @@ namespace geode {
|
|||
virtual void enable();
|
||||
virtual void disable();
|
||||
virtual ListenerResult passThrough(Event*) = 0;
|
||||
virtual ~EventListenerProtocol();
|
||||
};
|
||||
|
||||
template <typename C, typename T>
|
||||
|
@ -64,12 +65,20 @@ namespace geode {
|
|||
return ListenerResult::Propagate;
|
||||
}
|
||||
|
||||
EventListener(T filter = T()) {}
|
||||
EventListener(std::function<Callback> fn, T filter = T()) : m_callback(fn), m_filter(filter) {}
|
||||
EventListener(Callback* fnptr, T filter = T()) : m_callback(fnptr), m_filter(filter) {}
|
||||
EventListener(T filter = T()) {
|
||||
this->enable();
|
||||
}
|
||||
EventListener(std::function<Callback> fn, T filter = T()) : m_callback(fn), m_filter(filter) {
|
||||
this->enable();
|
||||
}
|
||||
EventListener(Callback* fnptr, T filter = T()) : m_callback(fnptr), m_filter(filter) {
|
||||
this->enable();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
void bind(std::function<Callback> fn) {
|
||||
m_callback = fn;
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#include <Geode/DefaultInclude.hpp>
|
||||
#include <Geode/hook-core/Hook.hpp>
|
||||
#include <Geode/utils/types.hpp>
|
||||
#include "../DefaultInclude.hpp"
|
||||
#include "../hook-core/Hook.hpp"
|
||||
#include "../utils/general.hpp"
|
||||
#include "../external/json/json.hpp"
|
||||
#include <inttypes.h>
|
||||
#include <string_view>
|
||||
|
||||
|
@ -77,6 +78,12 @@ namespace geode {
|
|||
Mod* getOwner() const {
|
||||
return m_owner;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get info about the hook as JSON
|
||||
* @note For IPC
|
||||
*/
|
||||
nlohmann::json getRuntimeInfo() const;
|
||||
};
|
||||
|
||||
class GEODE_DLL Patch {
|
||||
|
@ -128,5 +135,11 @@ namespace geode {
|
|||
Mod* getOwner() const {
|
||||
return m_owner;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get info about the patch as JSON
|
||||
* @note For IPC
|
||||
*/
|
||||
nlohmann::json getRuntimeInfo() const;
|
||||
};
|
||||
}
|
||||
|
|
90
loader/include/Geode/loader/IPC.hpp
Normal file
90
loader/include/Geode/loader/IPC.hpp
Normal file
|
@ -0,0 +1,90 @@
|
|||
#pragma once
|
||||
|
||||
#include "Event.hpp"
|
||||
#include "Loader.hpp"
|
||||
|
||||
namespace geode {
|
||||
#ifdef GEODE_IS_WINDOWS
|
||||
constexpr const char* IPC_PIPE_NAME = "\\\\.\\pipe\\GeodeIPCPipe";
|
||||
#endif
|
||||
|
||||
class IPCFilter;
|
||||
|
||||
// IPC (Inter-Process Communication) provides a way for Geode mods to talk
|
||||
// to other programs on the user's computer. If you have, for example, a
|
||||
// debugger, or an external modding UI, that application can open up the
|
||||
// platform-specific pipe and start sending messages to mods. Mods can
|
||||
// listen for messages using the listenForIPC function, and reply to
|
||||
// messages the get by using the reply method on the event provided. For
|
||||
// example, an external application can query what mods are loaded in Geode
|
||||
// by sending the `list-mods` message to `geode.loader`.
|
||||
|
||||
class GEODE_DLL IPCEvent : public Event {
|
||||
protected:
|
||||
void* m_rawPipeHandle;
|
||||
std::string m_targetModID;
|
||||
std::optional<std::string> m_replyID;
|
||||
std::string m_messageID;
|
||||
nlohmann::json m_messageData;
|
||||
bool m_replied = false;
|
||||
|
||||
/**
|
||||
* Reply to the message. Will post a message back to the application
|
||||
* the sent this message with the reply ID and provided data.
|
||||
* You can only reply once; after the other application has received
|
||||
* the reply, it can assume the reply ID can be freed and reused for
|
||||
* other messages. Calling reply again on this message will not cause
|
||||
* a new response to be sent.
|
||||
* If reply is not explicitly called, a default response of null will
|
||||
* be posted back.
|
||||
* @param data The data to send back; will be the under the "data" key
|
||||
* in the response JSON. The structure may be anything; however, you
|
||||
* should document what kind of JSON structures applications may expect
|
||||
* from your mod.
|
||||
*/
|
||||
void reply(nlohmann::json const& data);
|
||||
|
||||
friend class IPCFilter;
|
||||
|
||||
public:
|
||||
IPCEvent(
|
||||
void* rawPipeHandle,
|
||||
std::string const& targetModID,
|
||||
std::string const& messageID,
|
||||
std::optional<std::string> const& replyID,
|
||||
nlohmann::json const& messageData
|
||||
);
|
||||
virtual ~IPCEvent();
|
||||
|
||||
std::optional<std::string> getReplyID() const;
|
||||
std::string getTargetModID() const;
|
||||
std::string getMessageID() const;
|
||||
nlohmann::json getMessageData() const;
|
||||
};
|
||||
|
||||
class GEODE_DLL IPCFilter : public EventFilter<IPCEvent> {
|
||||
public:
|
||||
using Callback = nlohmann::json(IPCEvent*);
|
||||
|
||||
protected:
|
||||
std::string m_modID;
|
||||
std::string m_messageID;
|
||||
|
||||
public:
|
||||
ListenerResult handle(std::function<Callback> fn, IPCEvent* event);
|
||||
IPCFilter(
|
||||
std::string const& modID,
|
||||
std::string const& messageID
|
||||
);
|
||||
};
|
||||
|
||||
template<class = void>
|
||||
std::monostate listenForIPC(std::string const& messageID, nlohmann::json(*callback)(IPCEvent*)) {
|
||||
Loader::get()->scheduleOnModLoad(getMod(), [=]() {
|
||||
new EventListener(
|
||||
callback, IPCFilter(getMod()->getID(), messageID)
|
||||
);
|
||||
});
|
||||
return std::monostate();
|
||||
}
|
||||
}
|
|
@ -11,7 +11,18 @@
|
|||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
#include <fs/filesystem.hpp>
|
||||
#include "Log.hpp"
|
||||
#include <mutex>
|
||||
|
||||
// for some reason std::filesystem::path doesn't have std::hash defined in C++17
|
||||
// and ghc seems to have inherited this limitation
|
||||
template<>
|
||||
struct std::hash<ghc::filesystem::path> {
|
||||
std::size_t operator()(ghc::filesystem::path const& path) const noexcept {
|
||||
return ghc::filesystem::hash_value(path);
|
||||
}
|
||||
};
|
||||
|
||||
namespace geode {
|
||||
#pragma warning(disable : 4251)
|
||||
|
@ -46,6 +57,7 @@ namespace geode {
|
|||
class GEODE_DLL Loader {
|
||||
public:
|
||||
struct FailedModInfo {
|
||||
// todo: change to path
|
||||
std::string m_file;
|
||||
std::string m_reason;
|
||||
};
|
||||
|
@ -57,6 +69,8 @@ namespace geode {
|
|||
};
|
||||
|
||||
std::unordered_map<std::string, ModSettings> m_mods;
|
||||
// todo: in v1.0.0, make this a customizable option in mod.json
|
||||
std::unordered_set<ghc::filesystem::path> m_earlyLoadMods;
|
||||
};
|
||||
|
||||
using ScheduledFunction = std::function<void GEODE_CALL(void)>;
|
||||
|
@ -70,7 +84,8 @@ namespace geode {
|
|||
std::vector<ghc::filesystem::path> m_texturePaths;
|
||||
LoaderSettings m_loadedSettings;
|
||||
bool m_isSetup = false;
|
||||
static bool s_unloading;
|
||||
static std::atomic_bool s_unloading;
|
||||
mutable std::mutex m_modLoadMutex;
|
||||
|
||||
Result<std::string> createTempDirectoryForMod(ModInfo const& info);
|
||||
Result<Mod*> loadModFromFile(std::string const& file);
|
||||
|
@ -87,8 +102,7 @@ namespace geode {
|
|||
|
||||
template <class, class>
|
||||
friend class modifier::FieldIntermediate;
|
||||
|
||||
void updateResourcePaths();
|
||||
|
||||
void updateModResources(Mod* mod);
|
||||
|
||||
// used internally in geode_implicit_load
|
||||
|
@ -110,7 +124,9 @@ namespace geode {
|
|||
|
||||
Result<> saveSettings();
|
||||
Result<> loadSettings();
|
||||
|
||||
Result<> saveData();
|
||||
Result<> loadData();
|
||||
|
||||
bool didLastLaunchCrash() const;
|
||||
ghc::filesystem::path getCrashLogDirectory() const;
|
||||
|
||||
|
@ -180,12 +196,17 @@ namespace geode {
|
|||
|
||||
void clearLogs();
|
||||
|
||||
/**
|
||||
* Do not call manually unless you know what you're doing.
|
||||
*/
|
||||
void updateResourcePaths();
|
||||
/**
|
||||
* Do not call manually unless you know what you're doing.
|
||||
*/
|
||||
void updateResources();
|
||||
void addTexturePath(ghc::filesystem::path const& path);
|
||||
void removeTexturePath(ghc::filesystem::path const& path);
|
||||
std::vector<ghc::filesystem::path> getTexturePaths() const;
|
||||
|
||||
/**
|
||||
* Check if a mod with an ID is installed. Any
|
||||
|
@ -267,5 +288,9 @@ namespace geode {
|
|||
* Close the platform-specific external console (if one exists)
|
||||
*/
|
||||
static void closePlatfromConsole();
|
||||
|
||||
void waitForModsToBeLoaded();
|
||||
void setEarlyLoadMod(Mod* mod, bool enabled);
|
||||
bool shouldEarlyLoadMod(Mod* mod) const;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -4,11 +4,12 @@
|
|||
#include "Setting.hpp"
|
||||
#include "Types.hpp"
|
||||
|
||||
#include <Geode/DefaultInclude.hpp>
|
||||
#include <Geode/utils/Result.hpp>
|
||||
#include <Geode/utils/VersionInfo.hpp>
|
||||
#include <Geode/utils/json.hpp>
|
||||
#include <Geode/utils/types.hpp>
|
||||
#include "../DefaultInclude.hpp"
|
||||
#include "../utils/Result.hpp"
|
||||
#include "../utils/VersionInfo.hpp"
|
||||
#include "../external/json/json.hpp"
|
||||
#include "../utils/general.hpp"
|
||||
#include "../cocos/support/zip_support/ZipUtils.h"
|
||||
#include <optional>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
|
@ -143,10 +144,6 @@ namespace geode {
|
|||
* Mod spritesheet names
|
||||
*/
|
||||
std::vector<std::string> m_spritesheets;
|
||||
/**
|
||||
* Default data store values
|
||||
*/
|
||||
nlohmann::json m_defaultDataStore;
|
||||
/**
|
||||
* Mod settings
|
||||
*/
|
||||
|
@ -172,7 +169,19 @@ namespace geode {
|
|||
*/
|
||||
static Result<ModInfo> create(ModJson const& json);
|
||||
|
||||
/**
|
||||
* Convert to JSON. Essentially same as getRawJSON except dynamically
|
||||
* adds runtime fields like path
|
||||
*/
|
||||
ModJson toJSON() const;
|
||||
/**
|
||||
* Get the raw JSON file
|
||||
*/
|
||||
ModJson getRawJSON() const;
|
||||
|
||||
private:
|
||||
ModJson m_rawJSON;
|
||||
|
||||
/**
|
||||
* Version is passed for backwards
|
||||
* compatibility if we update the mod.json
|
||||
|
@ -186,27 +195,21 @@ namespace geode {
|
|||
std::vector<std::pair<std::string, std::optional<std::string>*>> getSpecialFiles();
|
||||
};
|
||||
|
||||
/**
|
||||
* @class DataStore
|
||||
* Internal class for notifying Mod
|
||||
* when the datastore changes
|
||||
*/
|
||||
class GEODE_DLL DataStore {
|
||||
nlohmann::json m_store;
|
||||
// For converting ModInfo back to JSON
|
||||
void GEODE_DLL to_json(nlohmann::json& json, ModInfo const& info);
|
||||
|
||||
template<class T>
|
||||
struct HandleToSaved : public T {
|
||||
Mod* m_mod;
|
||||
std::string m_key;
|
||||
|
||||
DataStore(Mod* m, nlohmann::json& j) : m_mod(m), m_store(j) {}
|
||||
|
||||
friend class Mod;
|
||||
|
||||
public:
|
||||
~DataStore();
|
||||
|
||||
nlohmann::json& getJson() const;
|
||||
nlohmann::json& operator[](std::string const&);
|
||||
DataStore& operator=(nlohmann::json&);
|
||||
bool contains(std::string const&) const;
|
||||
operator nlohmann::json();
|
||||
HandleToSaved(std::string const& key, Mod* mod, T const& value)
|
||||
: T(value),
|
||||
m_key(key),
|
||||
m_mod(mod) {}
|
||||
HandleToSaved(HandleToSaved const&) = delete;
|
||||
HandleToSaved(HandleToSaved&&) = delete;
|
||||
~HandleToSaved();
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -293,9 +296,9 @@ namespace geode {
|
|||
std::string m_loadErrorInfo = "";
|
||||
|
||||
/**
|
||||
* Data Store object
|
||||
* Saved values
|
||||
*/
|
||||
nlohmann::json m_dataStore;
|
||||
nlohmann::json m_saved;
|
||||
|
||||
/**
|
||||
* Load the platform binary
|
||||
|
@ -306,8 +309,6 @@ namespace geode {
|
|||
Result<> saveSettings();
|
||||
Result<> loadSettings();
|
||||
|
||||
void postDSUpdate();
|
||||
|
||||
Result<> createTempDir();
|
||||
|
||||
static bool validateID(std::string const& id);
|
||||
|
@ -326,7 +327,6 @@ namespace geode {
|
|||
friend class Loader;
|
||||
friend class ::InternalLoader;
|
||||
friend struct ModInfo;
|
||||
friend class DataStore;
|
||||
|
||||
template <class = void>
|
||||
static inline GEODE_HIDDEN Mod* sharedMod = nullptr;
|
||||
|
@ -357,6 +357,10 @@ namespace geode {
|
|||
ModInfo getModInfo() const;
|
||||
ghc::filesystem::path getTempDir() const;
|
||||
ghc::filesystem::path getBinaryPath() const;
|
||||
|
||||
Result<> saveData();
|
||||
Result<> loadData();
|
||||
|
||||
/**
|
||||
* Get the mod's save directory path
|
||||
*/
|
||||
|
@ -364,7 +368,7 @@ namespace geode {
|
|||
/**
|
||||
* Get the mod's config directory path
|
||||
*/
|
||||
ghc::filesystem::path getConfigDir() const;
|
||||
ghc::filesystem::path getConfigDir(bool create = true) const;
|
||||
|
||||
bool hasSettings() const;
|
||||
decltype(ModInfo::m_settings) getSettings() const;
|
||||
|
@ -388,6 +392,50 @@ namespace geode {
|
|||
return false;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T getSavedValue(std::string const& key) {
|
||||
if (m_saved.count(key)) {
|
||||
try {
|
||||
// json -> T may fail
|
||||
return m_saved.at(key);
|
||||
} catch(...) {}
|
||||
}
|
||||
return T();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T getSavedValue(std::string const& key, T const& defaultValue) {
|
||||
if (m_saved.count(key)) {
|
||||
try {
|
||||
// json -> T may fail
|
||||
return m_saved.at(key);
|
||||
} catch(...) {}
|
||||
}
|
||||
m_saved[key] = defaultValue;
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
HandleToSaved<T> getSavedMutable(std::string const& key) {
|
||||
return HandleToSaved(key, this, this->getSavedValue<T>(key));
|
||||
}
|
||||
|
||||
template<class T>
|
||||
HandleToSaved<T> getSavedMutable(std::string const& key, T const& defaultValue) {
|
||||
return HandleToSaved(key, this, this->getSavedValue<T>(key, defaultValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of an automatically saved variable. When the game is
|
||||
* closed, the value is automatically saved under the key
|
||||
* @param key Key of the saved value
|
||||
* @param value Value
|
||||
*/
|
||||
template<class T>
|
||||
void setSavedValue(std::string const& key, T const& value) {
|
||||
m_saved[key] = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mod container stored in the Interface
|
||||
* @returns nullptr if Interface is not initialized,
|
||||
|
@ -517,19 +565,6 @@ namespace geode {
|
|||
Result<> uninstall();
|
||||
bool isUninstalled() const;
|
||||
|
||||
/**
|
||||
* Return the data store object
|
||||
* @returns DataStore object
|
||||
* store
|
||||
*/
|
||||
DataStore getDataStore();
|
||||
|
||||
/**
|
||||
* Reset the data store to the
|
||||
* default value
|
||||
*/
|
||||
Result<> resetDataStore();
|
||||
|
||||
/**
|
||||
* Check whether or not this Mod
|
||||
* depends on another mod
|
||||
|
@ -562,8 +597,19 @@ namespace geode {
|
|||
std::vector<Dependency> getUnresolvedDependencies();
|
||||
|
||||
char const* expandSpriteName(char const* name);
|
||||
|
||||
/**
|
||||
* Get info about the mod as JSON
|
||||
* @note For IPC
|
||||
*/
|
||||
ModJson getRuntimeInfo() const;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
HandleToSaved<T>::~HandleToSaved() {
|
||||
m_mod->setSavedValue(m_key, static_cast<T>(*this));
|
||||
}
|
||||
|
||||
/**
|
||||
* To bypass the need for cyclic dependencies,
|
||||
* this function does the exact same as Mod::get()
|
||||
|
@ -578,3 +624,6 @@ namespace geode {
|
|||
inline char const* operator"" _spr(char const* str, size_t) {
|
||||
return geode::Mod::get()->expandSpriteName(str);
|
||||
}
|
||||
|
||||
// this header uses Mod
|
||||
#include "ModEvent.hpp"
|
||||
|
|
57
loader/include/Geode/loader/ModEvent.hpp
Normal file
57
loader/include/Geode/loader/ModEvent.hpp
Normal file
|
@ -0,0 +1,57 @@
|
|||
#pragma once
|
||||
|
||||
#include "Event.hpp"
|
||||
#include <optional>
|
||||
#include "Mod.hpp"
|
||||
|
||||
namespace geode {
|
||||
enum class ModEventType {
|
||||
Loaded,
|
||||
Unloaded,
|
||||
Enabled,
|
||||
Disabled,
|
||||
DataLoaded,
|
||||
DataSaved,
|
||||
};
|
||||
|
||||
class GEODE_DLL ModStateEvent : public Event {
|
||||
protected:
|
||||
ModEventType m_type;
|
||||
Mod* m_mod;
|
||||
|
||||
public:
|
||||
ModStateEvent(Mod* mod, ModEventType type);
|
||||
ModEventType getType() const;
|
||||
Mod* getMod() const;
|
||||
};
|
||||
|
||||
class GEODE_DLL ModStateFilter : public EventFilter<ModStateEvent> {
|
||||
public:
|
||||
using Callback = void(ModStateEvent*);
|
||||
|
||||
protected:
|
||||
ModEventType m_type;
|
||||
Mod* m_mod;
|
||||
|
||||
public:
|
||||
ListenerResult handle(std::function<Callback> fn, ModStateEvent* event);
|
||||
ModStateFilter(Mod* mod, ModEventType type);
|
||||
};
|
||||
}
|
||||
|
||||
#define $on_mod(type) \
|
||||
template<class> \
|
||||
void GEODE_CONCAT(geodeExecFunction, __LINE__)(ModStateEvent*); \
|
||||
namespace { \
|
||||
struct GEODE_CONCAT(ExecFuncUnique, __LINE__) {}; \
|
||||
} \
|
||||
static inline auto GEODE_CONCAT(Exec, __LINE__) = (geode::Loader::get()->scheduleOnModLoad(\
|
||||
geode::Mod::get(), []() { \
|
||||
static auto _ = geode::EventListener( \
|
||||
&GEODE_CONCAT(geodeExecFunction, __LINE__)<GEODE_CONCAT(ExecFuncUnique, __LINE__)>,\
|
||||
geode::ModStateFilter(geode::Mod::get(), geode::ModEventType::type)\
|
||||
); \
|
||||
} \
|
||||
), 0); \
|
||||
template<class> \
|
||||
void GEODE_CONCAT(geodeExecFunction, __LINE__)(ModStateEvent*)
|
|
@ -1,13 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
#include <Geode/DefaultInclude.hpp>
|
||||
#include <Geode/utils/JsonValidation.hpp>
|
||||
#include <Geode/utils/Result.hpp>
|
||||
#include <Geode/utils/container.hpp>
|
||||
#include <Geode/utils/convert.hpp>
|
||||
#include <Geode/utils/json.hpp>
|
||||
#include <Geode/utils/platform.hpp>
|
||||
#include <Geode/utils/ranges.hpp>
|
||||
#include "../DefaultInclude.hpp"
|
||||
#include "../utils/JsonValidation.hpp"
|
||||
#include "../utils/Result.hpp"
|
||||
#include "../external/json/json.hpp"
|
||||
#include "../utils/file.hpp"
|
||||
#include "../utils/ranges.hpp"
|
||||
#include "../utils/cocos.hpp"
|
||||
#include <optional>
|
||||
#include <regex>
|
||||
#include <unordered_set>
|
||||
|
@ -81,7 +80,7 @@ namespace geode {
|
|||
#define GEODE_INT_PARSE_SETTING_IMPL(obj, func, ...) \
|
||||
if constexpr (std::is_base_of_v<__VA_ARGS__, Class>) { \
|
||||
auto r = std::static_pointer_cast<Class>(res)->func(obj); \
|
||||
if (!r) return Err(r.error()); \
|
||||
if (!r) return Err(r.unwrapErr()); \
|
||||
}
|
||||
|
||||
#define GEODE_INT_CONSTRAIN_SETTING_CAN_IMPL(func, ...) \
|
||||
|
|
|
@ -52,19 +52,23 @@ namespace geode {
|
|||
};
|
||||
|
||||
template <class T>
|
||||
|
||||
requires std::is_base_of_v<Setting, T> std::monostate listenForSettingChanges(
|
||||
requires std::is_base_of_v<Setting, T>
|
||||
std::monostate listenForSettingChanges(
|
||||
std::string const& settingID, void (*callback)(T*)
|
||||
) {
|
||||
Loader::get()->scheduleOnModLoad(getMod(), [=]() {
|
||||
static auto _ = EventListener(callback, SettingChangedFilter<T>(getMod()->getID(), settingID));
|
||||
new EventListener(
|
||||
callback, SettingChangedFilter<T>(getMod()->getID(), settingID)
|
||||
);
|
||||
});
|
||||
return std::monostate();
|
||||
}
|
||||
|
||||
static std::monostate listenForAllSettingChanges(void (*callback)(Setting*)) {
|
||||
Loader::get()->scheduleOnModLoad(getMod(), [=]() {
|
||||
static auto _ = EventListener(callback, SettingChangedFilter(getMod()->getID()));
|
||||
new EventListener(
|
||||
callback, SettingChangedFilter(getMod()->getID())
|
||||
);
|
||||
});
|
||||
return std::monostate();
|
||||
}
|
||||
|
|
|
@ -148,18 +148,22 @@ namespace geode {
|
|||
Disabled,
|
||||
};
|
||||
|
||||
/**
|
||||
* Default Geode load method for C++
|
||||
* mods: The mod receive a pointer to
|
||||
* its allocated Mod instance. Return
|
||||
* true on a succesful load,
|
||||
* return false on error.
|
||||
*/
|
||||
typedef bool(GEODE_CALL* geode_load)(Mod*);
|
||||
typedef void(GEODE_CALL* geode_unload)();
|
||||
typedef bool(GEODE_CALL* geode_enable)();
|
||||
typedef bool(GEODE_CALL* geode_disable)();
|
||||
typedef bool(GEODE_CALL* geode_save_data)(char const*);
|
||||
typedef bool(GEODE_CALL* geode_load_data)(char const*);
|
||||
typedef void(GEODE_CALL* geode_setting_updated)(char const*, Setting*);
|
||||
/**
|
||||
* These methods will be removed in v1.0.0 and replaced with events
|
||||
*/
|
||||
|
||||
/**
|
||||
* Default Geode load method for C++
|
||||
* mods: The mod receive a pointer to
|
||||
* its allocated Mod instance. Return
|
||||
* true on a succesful load,
|
||||
* return false on error.
|
||||
*/
|
||||
typedef bool(GEODE_CALL* geode_load)(Mod*);
|
||||
typedef void(GEODE_CALL* geode_unload)();
|
||||
typedef bool(GEODE_CALL* geode_enable)();
|
||||
typedef bool(GEODE_CALL* geode_disable)();
|
||||
typedef bool(GEODE_CALL* geode_save_data)(const char*);
|
||||
typedef bool(GEODE_CALL* geode_load_data)(const char*);
|
||||
typedef void(GEODE_CALL* geode_setting_updated)(const char*, Setting*);
|
||||
}
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <Geode/platform/cplatform.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void GEODE_C_DLL geode_mod_log(void* mod, char const* message);
|
||||
|
||||
bool GEODE_C_DLL geode_mod_add_hook(void* mod, void* address, void* detour);
|
||||
|
||||
bool GEODE_C_DLL geode_get_last_error(char* buffer, size_t bufferSize);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -1,9 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
namespace geode {
|
||||
using dylib_t = void*;
|
||||
|
||||
struct PlatformInfo {
|
||||
dylib_t m_dylib;
|
||||
};
|
||||
}
|
70
loader/include/Geode/modify/IDManager.hpp
Normal file
70
loader/include/Geode/modify/IDManager.hpp
Normal file
|
@ -0,0 +1,70 @@
|
|||
#pragma once
|
||||
|
||||
#include "../DefaultInclude.hpp"
|
||||
#include "../ui/EnterLayerEvent.hpp"
|
||||
|
||||
namespace cocos2d {
|
||||
class CCNode;
|
||||
}
|
||||
|
||||
namespace geode {
|
||||
template<class T>
|
||||
concept IDProvidable = std::is_base_of_v<cocos2d::CCNode, T> && requires {
|
||||
{ T::CLASS_NAME } -> std::convertible_to<const char*>;
|
||||
};
|
||||
|
||||
class GEODE_DLL NodeIDs {
|
||||
public:
|
||||
template<class T>
|
||||
using Provider = void(GEODE_CALL*)(T*);
|
||||
|
||||
protected:
|
||||
std::unordered_map<std::string, Provider<cocos2d::CCNode>> m_providers;
|
||||
|
||||
public:
|
||||
static NodeIDs* get();
|
||||
|
||||
template<IDProvidable T>
|
||||
void registerProvider(void(GEODE_CALL* fun)(T*)) {
|
||||
m_providers.insert({
|
||||
T::CLASS_NAME,
|
||||
reinterpret_cast<Provider<cocos2d::CCNode>>(fun)
|
||||
});
|
||||
}
|
||||
|
||||
template<IDProvidable T>
|
||||
bool provide(T* layer) const {
|
||||
if (m_providers.count(T::CLASS_NAME)) {
|
||||
m_providers.at(T::CLASS_NAME)(layer);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// @note Because NodeIDs::provideFor(this) looks really neat
|
||||
template<IDProvidable T>
|
||||
static bool provideFor(T* layer) {
|
||||
return NodeIDs::get()->provide(layer);
|
||||
}
|
||||
};
|
||||
|
||||
template<IDProvidable For>
|
||||
void GEODE_CALL geodeInternalProvideIDsFor(For* cls) {
|
||||
if (cls->getID() != For::CLASS_NAME) {
|
||||
cls->setID(For::CLASS_NAME);
|
||||
cls->provide();
|
||||
EnterLayerEvent(For::CLASS_NAME, cls).post();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define $register_ids(Layer_) \
|
||||
struct GEODE_CONCAT(ProvideIDsFor, Layer_) : public Layer_ {\
|
||||
void provide();\
|
||||
};\
|
||||
$execute {\
|
||||
NodeIDs::get()->registerProvider(\
|
||||
&geodeInternalProvideIDsFor<GEODE_CONCAT(ProvideIDsFor, Layer_)>\
|
||||
);\
|
||||
};\
|
||||
void GEODE_CONCAT(ProvideIDsFor, Layer_)::provide()
|
|
@ -56,16 +56,20 @@
|
|||
*/
|
||||
#define $cls std::remove_pointer<decltype(this)>::type
|
||||
|
||||
#define GEODE_EXECUTE_FUNC(Line_) \
|
||||
template <class> \
|
||||
void _##Line_##Function(); \
|
||||
namespace { \
|
||||
struct _##Line_##Unique {}; \
|
||||
} \
|
||||
static inline auto _line = \
|
||||
(Loader::get()->scheduleOnModLoad(nullptr, &_##Line_##Function<_##Line_##Unique>), 0); \
|
||||
template <class> \
|
||||
void _##Line_##Function()
|
||||
#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 GEODE_EXECUTE_FUNC1(Line_) GEODE_EXECUTE_FUNC(Line_)
|
||||
#define $execute GEODE_EXECUTE_FUNC1(__LINE__)
|
||||
|
||||
#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__)()
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <Geode/loader/Loader.hpp>
|
||||
#include <Geode/loader/Mod.hpp>
|
||||
#include <iostream>
|
||||
#include "IDManager.hpp"
|
||||
|
||||
#define GEODE_APPLY_MODIFY_FOR_FUNCTION( \
|
||||
addr_index, pure_index, convention, className, functionName \
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#define GEODE_C_DLL
|
||||
#define GEODE_C_API
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4099) // type first seen as class
|
||||
#pragma warning(default : 4067)
|
||||
|
@ -20,16 +17,6 @@
|
|||
#define GEODE_CALL __stdcall
|
||||
#define GEODE_PLATFORM_EXTENSION ".dll"
|
||||
#define GEODE_PLATFORM_SHORT_IDENTIFIER "win"
|
||||
|
||||
#ifdef GEODE_EXPORTING
|
||||
#undef GEODE_C_DLL
|
||||
#define GEODE_C_DLL __declspec(dllexport)
|
||||
#else
|
||||
#undef GEODE_C_DLL
|
||||
#define GEODE_C_DLL __declspec(dllimport)
|
||||
#endif
|
||||
#undef GEODE_C_API
|
||||
#define GEODE_C_API __declspec(dllexport) __stdcall
|
||||
#else
|
||||
#define GEODE_WINDOWS(...)
|
||||
#endif
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "Popup.hpp"
|
||||
#include "InputNode.hpp"
|
||||
#include "Popup.hpp"
|
||||
|
||||
|
|
47
loader/include/Geode/ui/Colors.hpp
Normal file
47
loader/include/Geode/ui/Colors.hpp
Normal file
|
@ -0,0 +1,47 @@
|
|||
#pragma once
|
||||
|
||||
#include "../DefaultInclude.hpp"
|
||||
#include "../loader/Mod.hpp"
|
||||
#include <cocos2d.h>
|
||||
|
||||
namespace geode {
|
||||
// Credit to https://github.com/Ikszyon/UI-Recolor for many of these addresses!
|
||||
|
||||
/**
|
||||
* Hardcoded GD colors
|
||||
*/
|
||||
enum class GDColor {
|
||||
NormalModeProgressBar,
|
||||
PracticeModeProgressBar,
|
||||
|
||||
ProfilePostBG,
|
||||
};
|
||||
|
||||
class GEODE_DLL ColorManager {
|
||||
protected:
|
||||
struct Value {
|
||||
cocos2d::ccColor3B value;
|
||||
Mod* setter;
|
||||
};
|
||||
|
||||
std::unordered_map<GDColor, std::vector<Value>> m_colors;
|
||||
|
||||
ColorManager();
|
||||
|
||||
public:
|
||||
static ColorManager* get();
|
||||
|
||||
cocos2d::ccColor3B getColor(GDColor color) const;
|
||||
void setColor(GDColor color, Mod* setter, cocos2d::ccColor3B const& value);
|
||||
void resetColor(GDColor color, Mod* setter);
|
||||
|
||||
template<class = void>
|
||||
void setColor(GDColor color, cocos2d::ccColor3B const& value) {
|
||||
this->setColor(color, Mod::get(), value);
|
||||
}
|
||||
template<class = void>
|
||||
void resetColor(GDColor color) {
|
||||
this->resetColor(color, Mod::get());
|
||||
}
|
||||
};
|
||||
}
|
80
loader/include/Geode/ui/EnterLayerEvent.hpp
Normal file
80
loader/include/Geode/ui/EnterLayerEvent.hpp
Normal file
|
@ -0,0 +1,80 @@
|
|||
#pragma once
|
||||
|
||||
#include "../loader/Event.hpp"
|
||||
|
||||
namespace cocos2d {
|
||||
class CCNode;
|
||||
}
|
||||
|
||||
namespace geode {
|
||||
template<class T>
|
||||
concept InheritsCCNode = std::is_base_of_v<cocos2d::CCNode, T>;
|
||||
|
||||
// Base class; exists so event listeners can be placed dynamically at runtime
|
||||
class GEODE_DLL AEnterLayerEvent : public Event {
|
||||
protected:
|
||||
std::string m_layerID;
|
||||
cocos2d::CCNode* m_layer;
|
||||
|
||||
public:
|
||||
AEnterLayerEvent(
|
||||
std::string const& layerID,
|
||||
cocos2d::CCNode* layer
|
||||
);
|
||||
|
||||
std::string getID() const;
|
||||
cocos2d::CCNode* getLayer() const;
|
||||
};
|
||||
|
||||
class GEODE_DLL AEnterLayerFilter : public EventFilter<AEnterLayerEvent> {
|
||||
public:
|
||||
using Callback = std::function<void(AEnterLayerEvent*)>;
|
||||
|
||||
protected:
|
||||
std::optional<std::string> m_targetID;
|
||||
|
||||
public:
|
||||
ListenerResult handle(Callback fn, AEnterLayerEvent* event);
|
||||
|
||||
AEnterLayerFilter(
|
||||
std::optional<std::string> const& id
|
||||
);
|
||||
};
|
||||
|
||||
template<InheritsCCNode T>
|
||||
class EnterLayerEvent : public AEnterLayerEvent {
|
||||
public:
|
||||
EnterLayerEvent(
|
||||
std::string const& layerID,
|
||||
T* layer
|
||||
) : AEnterLayerEvent(layerID, layer) {}
|
||||
|
||||
T* getLayer() const {
|
||||
return static_cast<T*>(m_layer);
|
||||
}
|
||||
};
|
||||
|
||||
template<class T, class N>
|
||||
concept InheritsEnterLayer = std::is_base_of_v<EnterLayerEvent<N>, T>;
|
||||
|
||||
template<class N, InheritsEnterLayer<N> T>
|
||||
class EnterLayerFilter : public EventFilter<EnterLayerEvent<N>> {
|
||||
public:
|
||||
using Callback = void(T*);
|
||||
|
||||
protected:
|
||||
std::optional<std::string> m_targetID;
|
||||
|
||||
public:
|
||||
ListenerResult handle(std::function<Callback> fn, EnterLayerEvent<N>* event) {
|
||||
if (m_targetID == event->getID()) {
|
||||
fn(static_cast<T*>(event));
|
||||
}
|
||||
return ListenerResult::Propagate;
|
||||
}
|
||||
|
||||
EnterLayerFilter(
|
||||
std::optional<std::string> const& id
|
||||
) : m_targetID(id) {}
|
||||
};
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "../utils/Ref.hpp"
|
||||
#include "../utils/cocos.hpp"
|
||||
#include "SceneManager.hpp"
|
||||
|
||||
#include <chrono>
|
||||
|
|
|
@ -68,15 +68,16 @@ namespace geode {
|
|||
}
|
||||
|
||||
void setTitle(
|
||||
char const* title, char const* font = "goldFont.fnt", float scale = .7f,
|
||||
std::string const& title,
|
||||
const char* font = "goldFont.fnt",
|
||||
float scale = .7f,
|
||||
float offset = 20.f
|
||||
) {
|
||||
if (m_title) {
|
||||
m_title->setString(title);
|
||||
}
|
||||
else {
|
||||
m_title->setString(title.c_str());
|
||||
} else {
|
||||
auto winSize = cocos2d::CCDirector::sharedDirector()->getWinSize();
|
||||
m_title = cocos2d::CCLabelBMFont::create(title, font);
|
||||
m_title = cocos2d::CCLabelBMFont::create(title.c_str(), font);
|
||||
m_title->setPosition(
|
||||
winSize.width / 2, winSize.height / 2 + m_size.height / 2 - offset
|
||||
);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "../loader/Log.hpp"
|
||||
#include "json.hpp"
|
||||
#include "../external/json/json.hpp"
|
||||
|
||||
#include <set>
|
||||
#include <variant>
|
||||
|
|
|
@ -1,277 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "../DefaultInclude.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <variant>
|
||||
|
||||
namespace geode {
|
||||
namespace {
|
||||
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 DefaultError = std::string;
|
||||
}
|
||||
|
||||
template <class T = DefaultValue, class E = DefaultError>
|
||||
class [[nodiscard]] NewResult {
|
||||
public:
|
||||
using value_type = std::remove_reference_t<T>;
|
||||
using error_type = std::remove_reference_t<E>;
|
||||
|
||||
// for some reason doing requires causes errors with pch...
|
||||
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:
|
||||
std::variant<value_type, error_type> m_value;
|
||||
|
||||
public:
|
||||
bool isOk() const {
|
||||
return std::holds_alternative<value_type>(m_value);
|
||||
}
|
||||
|
||||
bool isErr() const {
|
||||
return std::holds_alternative<error_type>(m_value);
|
||||
}
|
||||
|
||||
explicit NewResult(value_type const& value
|
||||
) requires std::is_copy_constructible_v<value_type> : m_value(value) {}
|
||||
|
||||
explicit NewResult(value_type&& value) requires std::is_move_constructible_v<value_type> :
|
||||
m_value(std::forward<value_type>(value)) {}
|
||||
|
||||
explicit NewResult(error_type const& value
|
||||
) requires std::is_copy_constructible_v<error_type> : m_value(value) {}
|
||||
|
||||
explicit NewResult(error_type&& value) requires std::is_move_constructible_v<error_type> :
|
||||
m_value(std::forward<error_type>(value)) {}
|
||||
|
||||
NewResult(NewResult<T, E> const& other) requires std::is_copy_constructible_v<value_type> &&
|
||||
std::is_copy_constructible_v<error_type>
|
||||
= default;
|
||||
|
||||
NewResult(NewResult<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 ConvertibleToResult<T2, T> && ConvertibleToResult<E2, E> NewResult(
|
||||
NewResult<T2, E2> const& other
|
||||
)
|
||||
|
||||
requires std::is_copy_constructible_v<value_type> &&
|
||||
std::is_copy_constructible_v<error_type> :
|
||||
m_value(other.isOk() ? other.unwrap() : other.unwrapErr()) {}
|
||||
|
||||
template <class T2, class E2>
|
||||
requires ConvertibleToResult<T2, T> && ConvertibleToResult<E2, E> NewResult(
|
||||
NewResult<T2, E2>&& other
|
||||
)
|
||||
|
||||
requires(!std::is_copy_constructible_v<value_type> || !std::is_copy_constructible_v<error_type>) :
|
||||
m_value(other.isOk() ? other.unwrap() : other.unwrapErr()) {}
|
||||
|
||||
template <class T2>
|
||||
requires ConvertibleToResult<T2, T> NewResult(NewResult<T2, AnyType> const& other)
|
||||
|
||||
requires std::is_copy_constructible_v<value_type> &&
|
||||
std::is_copy_constructible_v<error_type> : NewResult(value_type(other.unwrap())) {}
|
||||
|
||||
template <class E2>
|
||||
requires ConvertibleToResult<E2, E> NewResult(NewResult<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())) {}
|
||||
|
||||
template <class T2>
|
||||
requires ConvertibleToResult<T2, T> NewResult(NewResult<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> NewResult(NewResult<AnyType, E2>&& other)
|
||||
|
||||
requires(!std::is_copy_constructible_v<value_type> || !std::is_copy_constructible_v<error_type>) :
|
||||
NewResult(std::forward<error_type>(other.unwrapErr())) {}
|
||||
|
||||
value_type unwrap() const requires std::is_copy_constructible_v<value_type> {
|
||||
return std::get<value_type>(m_value);
|
||||
}
|
||||
|
||||
value_type&& unwrap() requires(!std::is_copy_constructible_v<value_type>) {
|
||||
return std::move(std::get<value_type>(m_value));
|
||||
}
|
||||
|
||||
error_type unwrapErr() const requires std::is_copy_constructible_v<error_type> {
|
||||
return std::get<error_type>(m_value);
|
||||
}
|
||||
|
||||
error_type&& unwrapErr() requires(!std::is_copy_constructible_v<error_type>) {
|
||||
return std::move(std::get<error_type>(m_value));
|
||||
}
|
||||
|
||||
explicit operator bool() const
|
||||
requires(!std::is_same_v<T, bool> && !std::is_same_v<E, bool>) {
|
||||
return this->isOk();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class [[nodiscard]] NewResult<T, T> {
|
||||
public:
|
||||
using value_type = std::remove_reference_t<T>;
|
||||
using error_type = std::remove_reference_t<T>;
|
||||
|
||||
// for some reason doing requires causes errors with pch...
|
||||
static_assert(
|
||||
std::is_copy_constructible_v<value_type> || std::is_move_constructible_v<value_type>,
|
||||
"T must be copiable or movable!"
|
||||
);
|
||||
|
||||
protected:
|
||||
bool m_success;
|
||||
value_type m_value;
|
||||
|
||||
public:
|
||||
bool isOk() const {
|
||||
return m_success;
|
||||
}
|
||||
|
||||
bool isErr() const {
|
||||
return !m_success;
|
||||
}
|
||||
|
||||
explicit NewResult(value_type const& value, bool success) requires
|
||||
std::is_copy_constructible_v<value_type> :
|
||||
m_value(value),
|
||||
m_success(success) {}
|
||||
|
||||
explicit NewResult(value_type&& value, bool success) requires
|
||||
std::is_move_constructible_v<value_type> :
|
||||
m_value(std::forward<value_type>(value)),
|
||||
m_success(success) {}
|
||||
|
||||
NewResult(NewResult<T, T> const& other) requires std::is_copy_constructible_v<value_type>
|
||||
= default;
|
||||
|
||||
NewResult(NewResult<T, T>&& other
|
||||
) requires(!std::is_copy_constructible_v<value_type>) = default;
|
||||
|
||||
template <class T2, class E2>
|
||||
requires ConvertibleToResult<T2, T> && ConvertibleToResult<E2, T> NewResult(
|
||||
NewResult<T2, E2> const& other
|
||||
)
|
||||
|
||||
requires std::is_copy_constructible_v<value_type> :
|
||||
m_value(other.isOk() ? other.unwrap() : other.unwrapErr()),
|
||||
m_success(other.isOk()) {}
|
||||
|
||||
template <class T2, class E2>
|
||||
requires ConvertibleToResult<T2, T> && ConvertibleToResult<E2, T> NewResult(
|
||||
NewResult<T2, E2>&& other
|
||||
)
|
||||
|
||||
requires(!std::is_copy_constructible_v<value_type>) :
|
||||
m_value(other.isOk() ? other.unwrap() : other.unwrapErr()), m_success(other.isOk()) {}
|
||||
|
||||
template <class T2>
|
||||
requires ConvertibleToResult<T2, T> NewResult(NewResult<T2, AnyType> const& other)
|
||||
|
||||
requires std::is_copy_constructible_v<value_type> :
|
||||
NewResult(value_type(other.unwrap()), true) {}
|
||||
|
||||
template <class T2>
|
||||
requires ConvertibleToResult<T2, T> NewResult(NewResult<T2, AnyType>&& other)
|
||||
|
||||
requires(!std::is_copy_constructible_v<value_type>) :
|
||||
NewResult(std::forward<value_type>(other.unwrap()), true) {}
|
||||
|
||||
template <class E2>
|
||||
requires ConvertibleToResult<E2, T> NewResult(NewResult<AnyType, E2> const& other)
|
||||
|
||||
requires std::is_copy_constructible_v<value_type> :
|
||||
NewResult(error_type(other.unwrapErr()), false) {}
|
||||
|
||||
template <class E2>
|
||||
requires ConvertibleToResult<E2, T> NewResult(NewResult<AnyType, E2>&& other)
|
||||
|
||||
requires(!std::is_copy_constructible_v<value_type>) :
|
||||
NewResult(std::forward<error_type>(other.unwrapErr()), false) {}
|
||||
|
||||
value_type unwrap() const requires std::is_copy_constructible_v<value_type> {
|
||||
return m_value;
|
||||
}
|
||||
|
||||
value_type&& unwrap() requires(!std::is_copy_constructible_v<value_type>) {
|
||||
return std::move(m_value);
|
||||
}
|
||||
|
||||
error_type unwrapErr() const requires std::is_copy_constructible_v<error_type> {
|
||||
return m_value;
|
||||
}
|
||||
|
||||
error_type&& unwrapErr() requires(!std::is_copy_constructible_v<error_type>) {
|
||||
return std::move(m_value);
|
||||
}
|
||||
|
||||
explicit operator bool() const requires(!std::is_same_v<T, bool>) {
|
||||
return this->isOk();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T = DefaultValue, class E = AnyType>
|
||||
|
||||
requires std::is_copy_constructible_v<T> NewResult<T, E> NewOk(T value = T()) {
|
||||
return NewResult<T, E>(value);
|
||||
}
|
||||
|
||||
template <class T = DefaultValue, class E = AnyType>
|
||||
|
||||
requires(!std::is_copy_constructible_v<T>) NewResult<T, E> NewOk(T&& value) {
|
||||
return NewResult<T, E>(std::forward<T>(value));
|
||||
}
|
||||
|
||||
template <class E = DefaultError, class T = AnyType>
|
||||
|
||||
requires std::is_copy_constructible_v<E> NewResult<T, E> NewErr(E error = E()) {
|
||||
return NewResult<T, E>(error);
|
||||
}
|
||||
|
||||
template <class E = DefaultError, class T = AnyType>
|
||||
|
||||
requires(!std::is_copy_constructible_v<E>) NewResult<T, E> NewErr(E&& error) {
|
||||
return NewResult<T, E>(std::forward<E>(error));
|
||||
}
|
||||
|
||||
#define GEODE_UNWRAP_INTO(into, ...) \
|
||||
auto GEODE_CONCAT(res_, __LINE__) = (__VA_ARGS__); \
|
||||
if (GEODE_CONCAT(res_, __LINE__).isErr()) { \
|
||||
return Err(std::move(GEODE_CONCAT(res_, __LINE__).unwrapErr())); \
|
||||
} \
|
||||
into = std::move(GEODE_CONCAT(res_, __LINE__).unwrap())
|
||||
|
||||
#define GEODE_UNWRAP(...) \
|
||||
{ \
|
||||
auto GEODE_CONCAT(res_, __LINE__) = (__VA_ARGS__); \
|
||||
if (GEODE_CONCAT(res_, __LINE__).isErr()) { \
|
||||
return Err(std::move(GEODE_CONCAT(res_, __LINE__).unwrapErr())); \
|
||||
} \
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue