mirror of
https://github.com/geode-sdk/geode.git
synced 2024-11-14 19:15:05 -05:00
Merge branch 'main' into layout
This commit is contained in:
commit
61c0f1b274
41 changed files with 714 additions and 588 deletions
|
@ -79,11 +79,12 @@ IncludeCategories:
|
||||||
|
|
||||||
IndentAccessModifiers: false
|
IndentAccessModifiers: false
|
||||||
AccessModifierOffset: -4
|
AccessModifierOffset: -4
|
||||||
IndentCaseBlocks: true
|
IndentCaseBlocks: false
|
||||||
IndentCaseLabels: true
|
IndentCaseLabels: true
|
||||||
IndentExternBlock: Indent
|
IndentExternBlock: Indent
|
||||||
IndentGotoLabels: true
|
IndentGotoLabels: true
|
||||||
IndentPPDirectives: BeforeHash
|
IndentPPDirectives: BeforeHash
|
||||||
|
IndentRequiresClause: false
|
||||||
IndentWrappedFunctionNames: false
|
IndentWrappedFunctionNames: false
|
||||||
# InsertBraces: true
|
# InsertBraces: true
|
||||||
InsertTrailingCommas: None
|
InsertTrailingCommas: None
|
||||||
|
@ -107,6 +108,7 @@ PenaltyIndentedWhitespace: 0
|
||||||
|
|
||||||
QualifierAlignment: Right
|
QualifierAlignment: Right
|
||||||
|
|
||||||
|
RequiresClausePosition: OwnLine
|
||||||
ReflowComments: true
|
ReflowComments: true
|
||||||
SeparateDefinitionBlocks: Always
|
SeparateDefinitionBlocks: Always
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,6 @@ target_sources(${PROJECT_NAME} INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/entry.cpp)
|
||||||
|
|
||||||
add_subdirectory(codegen)
|
add_subdirectory(codegen)
|
||||||
|
|
||||||
message(STATUS ${GEODE_CODEGEN_PATH}/Geode/GeneratedSource.cpp)
|
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/bindings/GeometryDash.bro
|
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/bindings/GeometryDash.bro
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/bindings/Cocos2d.bro
|
${CMAKE_CURRENT_SOURCE_DIR}/bindings/Cocos2d.bro
|
||||||
|
@ -106,7 +105,7 @@ elseif(EXISTS ${GEODE_PLATFORM_BIN_PATH})
|
||||||
)
|
)
|
||||||
else()
|
else()
|
||||||
message(FATAL_ERROR
|
message(FATAL_ERROR
|
||||||
"No valid loader binary to link to! Install prebuilts with `geode sdk install-prebuilts` "
|
"No valid loader binary to link to! Install prebuilts with `geode sdk install-prebuilts`, "
|
||||||
"or build Geode from source."
|
"or build Geode from source and add `set(GEODE_LINK_NIGHTLY On)` to your CMakeLists.txt."
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -140,6 +140,8 @@ class cocos2d::CCDrawNode {
|
||||||
static cocos2d::CCDrawNode* create() = mac 0x378d00;
|
static cocos2d::CCDrawNode* create() = mac 0x378d00;
|
||||||
auto drawPolygon(cocos2d::CCPoint*, unsigned int, cocos2d::_ccColor4F const&, float, cocos2d::_ccColor4F const&) = mac 0x3797f0;
|
auto drawPolygon(cocos2d::CCPoint*, unsigned int, cocos2d::_ccColor4F const&, float, cocos2d::_ccColor4F const&) = mac 0x3797f0;
|
||||||
auto drawSegment(cocos2d::CCPoint const&, cocos2d::CCPoint const&, float, cocos2d::_ccColor4F const&) = mac 0x3792d0;
|
auto drawSegment(cocos2d::CCPoint const&, cocos2d::CCPoint const&, float, cocos2d::_ccColor4F const&) = mac 0x3792d0;
|
||||||
|
auto drawDot(cocos2d::CCPoint const&, float, cocos2d::_ccColor4F const&) = mac 0x379100;
|
||||||
|
|
||||||
auto getBlendFunc() const = mac 0x379ea0;
|
auto getBlendFunc() const = mac 0x379ea0;
|
||||||
auto init() = mac 0x378e00;
|
auto init() = mac 0x378e00;
|
||||||
auto setBlendFunc(cocos2d::_ccBlendFunc const&) = mac 0x379eb0;
|
auto setBlendFunc(cocos2d::_ccBlendFunc const&) = mac 0x379eb0;
|
||||||
|
@ -262,9 +264,8 @@ class cocos2d::CCLabelBMFont {
|
||||||
static cocos2d::CCLabelBMFont* create(char const*, char const*) = mac 0x347660;
|
static cocos2d::CCLabelBMFont* create(char const*, char const*) = mac 0x347660;
|
||||||
auto limitLabelWidth(float, float, float) = mac 0x34a6e0, ios 0x21b740;
|
auto limitLabelWidth(float, float, float) = mac 0x34a6e0, ios 0x21b740;
|
||||||
|
|
||||||
virtual ~CCLabelBMFont() = mac 0x347e80, ios 0x219afc;
|
|
||||||
|
|
||||||
virtual auto init() = mac 0x347b10, ios 0x2198e0;
|
virtual auto init() = mac 0x347b10, ios 0x2198e0;
|
||||||
|
bool initWithString(const char* str, const char* fnt, float width, cocos2d::CCTextAlignment align, cocos2d::CCPoint offset);
|
||||||
virtual auto setScaleX(float) = mac 0x34a5b0, ios 0x21b6e8;
|
virtual auto setScaleX(float) = mac 0x34a5b0, ios 0x21b6e8;
|
||||||
virtual auto setScaleY(float) = mac 0x34a5d0, ios 0x21b714;
|
virtual auto setScaleY(float) = mac 0x34a5d0, ios 0x21b714;
|
||||||
virtual auto setScale(float) = mac 0x34a590, ios 0x21b6bc;
|
virtual auto setScale(float) = mac 0x34a590, ios 0x21b6bc;
|
||||||
|
@ -292,6 +293,7 @@ class cocos2d::CCLabelBMFont {
|
||||||
virtual auto isCascadeColorEnabled() = mac 0x3493c0, ios 0x21aa3c;
|
virtual auto isCascadeColorEnabled() = mac 0x3493c0, ios 0x21aa3c;
|
||||||
virtual auto setCascadeColorEnabled(bool) = mac 0x3493e0, ios 0x21aa4c;
|
virtual auto setCascadeColorEnabled(bool) = mac 0x3493e0, ios 0x21aa4c;
|
||||||
virtual auto setString(unsigned short*, bool) = mac 0x348a60, ios 0x21a4b4;
|
virtual auto setString(unsigned short*, bool) = mac 0x348a60, ios 0x21a4b4;
|
||||||
|
virtual ~CCLabelBMFont() = mac 0x347e80;
|
||||||
}
|
}
|
||||||
|
|
||||||
class cocos2d::CCLabelTTF {
|
class cocos2d::CCLabelTTF {
|
||||||
|
@ -657,6 +659,7 @@ class cocos2d::CCRenderTexture {
|
||||||
auto end() = mac 0x35d2c0;
|
auto end() = mac 0x35d2c0;
|
||||||
static cocos2d::CCRenderTexture* create(int, int, cocos2d::CCTexture2DPixelFormat) = mac 0x35c720;
|
static cocos2d::CCRenderTexture* create(int, int, cocos2d::CCTexture2DPixelFormat) = mac 0x35c720;
|
||||||
auto newCCImage(bool) = mac 0x35d7d0;
|
auto newCCImage(bool) = mac 0x35d7d0;
|
||||||
|
auto saveToFile(char const*) = mac 0x35dab0;
|
||||||
}
|
}
|
||||||
|
|
||||||
class cocos2d::CCRepeat {
|
class cocos2d::CCRepeat {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
// geode additions to make stl containers easier
|
// geode additions to make stl containers easier
|
||||||
|
// clang-format off
|
||||||
class GDString {
|
class GDString {
|
||||||
void winDtor() = win 0xf6e0;
|
void winDtor() = win 0xf6e0;
|
||||||
char const* winCStr() = win 0xf710;
|
char const* winCStr() = win 0xf710;
|
||||||
|
@ -16,7 +17,6 @@ class GDString {
|
||||||
void macDestroy() = mac 0x489f78;
|
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;
|
||||||
|
|
||||||
|
@ -1104,6 +1104,17 @@ class EditorOptionsLayer {
|
||||||
}
|
}
|
||||||
|
|
||||||
class EditorPauseLayer : CCBlockLayer, FLAlertLayerProtocol {
|
class EditorPauseLayer : CCBlockLayer, FLAlertLayerProtocol {
|
||||||
|
static EditorPauseLayer* get() {
|
||||||
|
if (!EditorUI::get()) return nullptr;
|
||||||
|
|
||||||
|
auto editor = LevelEditorLayer::get();
|
||||||
|
for (auto i = 0; i < editor->getChildrenCount(); ++i) {
|
||||||
|
if (auto layer = cast::safe_cast<EditorPauseLayer*>(editor->getChildren()->objectAtIndex(i))) {
|
||||||
|
return layer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
static EditorPauseLayer* create(LevelEditorLayer* editor) {
|
static EditorPauseLayer* create(LevelEditorLayer* editor) {
|
||||||
auto pRet = new EditorPauseLayer();
|
auto pRet = new EditorPauseLayer();
|
||||||
if (pRet && pRet->init(editor)) {
|
if (pRet && pRet->init(editor)) {
|
||||||
|
@ -2105,6 +2116,14 @@ class GJGameLevel : cocos2d::CCNode {
|
||||||
GJDifficulty getAverageDifficulty() = win 0xbd9b0;
|
GJDifficulty getAverageDifficulty() = win 0xbd9b0;
|
||||||
gd::string getUnpackedLevelDescription() = win 0xbf890;
|
gd::string getUnpackedLevelDescription() = win 0xbf890;
|
||||||
|
|
||||||
|
static GJGameLevel* getCurrent() {
|
||||||
|
auto playLayer = PlayLayer::get();
|
||||||
|
if (playLayer) return playLayer->m_level;
|
||||||
|
auto editorLayer = LevelEditorLayer::get();
|
||||||
|
if (editorLayer) return editorLayer->m_level;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
cocos2d::CCDictionary* m_lastBuildSave;
|
cocos2d::CCDictionary* m_lastBuildSave;
|
||||||
int m_levelIDRand;
|
int m_levelIDRand;
|
||||||
int m_levelIDSeed;
|
int m_levelIDSeed;
|
||||||
|
@ -3550,10 +3569,10 @@ class LevelCell : TableViewCell {
|
||||||
}
|
}
|
||||||
|
|
||||||
class LevelCommentDelegate {
|
class LevelCommentDelegate {
|
||||||
virtual void loadCommentsFinished(cocos2d::CCArray *, const char*) {}
|
virtual void loadCommentsFinished(cocos2d::CCArray*, char const*) {}
|
||||||
virtual void loadCommentsFailed(const char*) {}
|
virtual void loadCommentsFailed(char const*) {}
|
||||||
virtual void updateUserScoreFinished() {}
|
virtual void updateUserScoreFinished() {}
|
||||||
virtual void setupPageInfo(gd::string, const char*) {}
|
virtual void setupPageInfo(gd::string, char const*) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
class LevelDeleteDelegate {
|
class LevelDeleteDelegate {
|
||||||
|
@ -3855,6 +3874,12 @@ class LevelSettingsObject : cocos2d::CCNode {
|
||||||
static LevelSettingsObject* objectFromString(gd::string) = mac 0x945a0, win 0x16f440;
|
static LevelSettingsObject* objectFromString(gd::string) = mac 0x945a0, win 0x16f440;
|
||||||
void setupColorsFromLegacyMode(cocos2d::CCDictionary*) = mac 0xa6a30, win 0x170050;
|
void setupColorsFromLegacyMode(cocos2d::CCDictionary*) = mac 0xa6a30, win 0x170050;
|
||||||
|
|
||||||
|
static LevelSettingsObject* get() {
|
||||||
|
auto baseLayer = GJBaseGameLayer::get();
|
||||||
|
if (baseLayer) return baseLayer->m_levelSettings;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
gd::string getSaveString() = mac 0x979c0, win 0x16ebf0;
|
gd::string getSaveString() = mac 0x979c0, win 0x16ebf0;
|
||||||
|
|
||||||
GJEffectManager* m_effectManager;
|
GJEffectManager* m_effectManager;
|
||||||
|
@ -4035,7 +4060,7 @@ class MusicDownloadManager : cocos2d::CCNode, PlatformDownloadDelegate {
|
||||||
cocos2d::CCDictionary* m_unknownDict;
|
cocos2d::CCDictionary* m_unknownDict;
|
||||||
cocos2d::CCArray* m_handlers;
|
cocos2d::CCArray* m_handlers;
|
||||||
cocos2d::CCDictionary* m_songsDict;
|
cocos2d::CCDictionary* m_songsDict;
|
||||||
int m_unknown;
|
int m_priority;
|
||||||
}
|
}
|
||||||
|
|
||||||
class NumberInputDelegate {
|
class NumberInputDelegate {
|
||||||
|
@ -5190,6 +5215,19 @@ class TableView : CCScrollLayerExt, CCScrollLayerExtDelegate {
|
||||||
static TableView* create(TableViewDelegate*, TableViewDataSource*, cocos2d::CCRect) = mac 0x37eb30, win 0x30ed0;
|
static TableView* create(TableViewDelegate*, TableViewDataSource*, cocos2d::CCRect) = mac 0x37eb30, win 0x30ed0;
|
||||||
void reloadData() = mac 0x37f970, win 0x317e0;
|
void reloadData() = mac 0x37f970, win 0x317e0;
|
||||||
|
|
||||||
|
virtual void onEnter() = mac 0x37ff30, ios 0x21dcac;
|
||||||
|
virtual void onExit() = mac 0x37ff40, ios 0x21dcb0;
|
||||||
|
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;
|
||||||
|
|
||||||
bool m_touchOutOfBoundary;
|
bool m_touchOutOfBoundary;
|
||||||
cocos2d::CCTouch* m_touchStart;
|
cocos2d::CCTouch* m_touchStart;
|
||||||
cocos2d::CCPoint m_touchStartPosition2;
|
cocos2d::CCPoint m_touchStartPosition2;
|
||||||
|
@ -5261,7 +5299,7 @@ class TeleportPortalObject : GameObject {
|
||||||
bool m_teleportEase;
|
bool m_teleportEase;
|
||||||
}
|
}
|
||||||
|
|
||||||
class TextAlertPopup {
|
class TextAlertPopup : cocos2d::CCNode {
|
||||||
static TextAlertPopup* create(gd::string const& text, float time, float scale) = win 0x1450b0;
|
static TextAlertPopup* create(gd::string const& text, float time, float scale) = win 0x1450b0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5372,4 +5410,4 @@ class VideoOptionsLayer : FLAlertLayer {
|
||||||
class LevelTools {
|
class LevelTools {
|
||||||
static gd::string base64DecodeString(gd::string) = mac 0x294510, win 0x18b3b0;
|
static gd::string base64DecodeString(gd::string) = mac 0x294510, win 0x18b3b0;
|
||||||
}
|
}
|
||||||
|
// clang-format on
|
||||||
|
|
|
@ -1,25 +1,27 @@
|
||||||
#include "Shared.hpp"
|
#include "Shared.hpp"
|
||||||
#include "TypeOpt.hpp"
|
#include "TypeOpt.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
namespace { namespace format_strings {
|
namespace {
|
||||||
char const* wrap_start = R"GEN(
|
namespace format_strings {
|
||||||
|
char const* wrap_start = R"GEN(
|
||||||
namespace wrap {
|
namespace wrap {
|
||||||
)GEN";
|
)GEN";
|
||||||
|
|
||||||
char const* wrap_declare_identifier = R"GEN(
|
char const* wrap_declare_identifier = R"GEN(
|
||||||
#ifndef GEODE_WRAP_{function_name}
|
#ifndef GEODE_WRAP_{function_name}
|
||||||
#define GEODE_WRAP_{function_name}
|
#define GEODE_WRAP_{function_name}
|
||||||
GEODE_WRAPPER_FOR_IDENTIFIER({function_name})
|
GEODE_WRAPPER_FOR_IDENTIFIER({function_name})
|
||||||
#endif
|
#endif
|
||||||
)GEN";
|
)GEN";
|
||||||
|
|
||||||
char const* wrap_end = R"GEN(
|
char const* wrap_end = R"GEN(
|
||||||
}
|
}
|
||||||
)GEN";
|
)GEN";
|
||||||
// requires: class_name
|
// requires: class_name
|
||||||
char const* modify_start = R"GEN(#pragma once
|
char const* modify_start = R"GEN(#pragma once
|
||||||
#include <Geode/modify/Modify.hpp>
|
#include <Geode/modify/Modify.hpp>
|
||||||
#include <Geode/modify/Field.hpp>
|
#include <Geode/modify/Field.hpp>
|
||||||
#include <Geode/modify/InternalMacros.hpp>
|
#include <Geode/modify/InternalMacros.hpp>
|
||||||
|
@ -28,100 +30,89 @@ using namespace geode::modifier;
|
||||||
namespace geode::modifier {{
|
namespace geode::modifier {{
|
||||||
{wrap}
|
{wrap}
|
||||||
template<class Derived>
|
template<class Derived>
|
||||||
struct Modify<Derived, {class_name}> : ModifyBase<Modify<Derived, {class_name}>> {{
|
struct ModifyDerive<Derived, {class_name}> : ModifyBase<ModifyDerive<Derived, {class_name}>> {{
|
||||||
using ModifyBase<Modify<Derived, {class_name}>>::ModifyBase;
|
using ModifyBase<ModifyDerive<Derived, {class_name}>>::ModifyBase;
|
||||||
using Base = {class_name};
|
using Base = {class_name};
|
||||||
static void apply() {{
|
static void apply() {{
|
||||||
using namespace geode::core::meta;
|
using namespace geode::core::meta;
|
||||||
|
|
||||||
)GEN";
|
)GEN";
|
||||||
|
|
||||||
// requires: index, class_name, arg_types, function_name, raw_arg_types, non_virtual
|
// requires: index, class_name, arg_types, function_name, raw_arg_types, non_virtual
|
||||||
char const* apply_function = R"GEN(
|
char const* apply_function = R"GEN(
|
||||||
GEODE_APPLY_MODIFY_FOR_FUNCTION({addr_index}, {pure_index}, {function_convention}, {class_name}, {function_name}))GEN";
|
GEODE_APPLY_MODIFY_FOR_FUNCTION({addr_index}, {pure_index}, {function_convention}, {class_name}, {function_name}))GEN";
|
||||||
|
|
||||||
char const* modify_end = R"GEN(
|
char const* modify_end = R"GEN(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
)GEN";
|
)GEN";
|
||||||
|
|
||||||
char const* modify_include = R"GEN(#include "modify/{file_name}"
|
char const* modify_include = R"GEN(#include "modify/{file_name}"
|
||||||
)GEN";
|
)GEN";
|
||||||
}}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string generateModifyHeader(Root& root, ghc::filesystem::path const& singleFolder) {
|
std::string generateModifyHeader(Root& root, ghc::filesystem::path const& singleFolder) {
|
||||||
std::string output;
|
std::string output;
|
||||||
|
|
||||||
TypeBank bank;
|
TypeBank bank;
|
||||||
bank.loadFrom(root);
|
bank.loadFrom(root);
|
||||||
|
|
||||||
for (auto c : root.classes) {
|
for (auto c : root.classes) {
|
||||||
if (c.name == "cocos2d")
|
if (c.name == "cocos2d") continue;
|
||||||
continue;
|
|
||||||
|
|
||||||
std::string filename = (codegen::getUnqualifiedClassName(c.name) + ".hpp");
|
std::string filename = (codegen::getUnqualifiedClassName(c.name) + ".hpp");
|
||||||
output += fmt::format(format_strings::modify_include,
|
output += fmt::format(format_strings::modify_include, fmt::arg("file_name", filename));
|
||||||
fmt::arg("file_name", filename)
|
|
||||||
);
|
|
||||||
|
|
||||||
std::string single_output;
|
std::string single_output;
|
||||||
std::string wrap;
|
std::string wrap;
|
||||||
|
|
||||||
// wrap
|
// wrap
|
||||||
wrap += format_strings::wrap_start;
|
wrap += format_strings::wrap_start;
|
||||||
std::set<std::string> used;
|
std::set<std::string> used;
|
||||||
for (auto& f : c.fields) {
|
for (auto& f : c.fields) {
|
||||||
if (auto fn = f.get_fn()) {
|
if (auto fn = f.get_fn()) {
|
||||||
if (fn->type == FunctionType::Normal && !used.count(fn->name)) {
|
if (fn->type == FunctionType::Normal && !used.count(fn->name)) {
|
||||||
used.insert(fn->name);
|
used.insert(fn->name);
|
||||||
wrap += fmt::format(format_strings::wrap_declare_identifier,
|
wrap += fmt::format(
|
||||||
fmt::arg("function_name", fn->name)
|
format_strings::wrap_declare_identifier, fmt::arg("function_name", fn->name)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wrap += format_strings::wrap_end;
|
wrap += format_strings::wrap_end;
|
||||||
|
|
||||||
single_output += fmt::format(format_strings::modify_start,
|
single_output += fmt::format(
|
||||||
fmt::arg("class_name", c.name),
|
format_strings::modify_start, fmt::arg("class_name", c.name), fmt::arg("wrap", wrap)
|
||||||
fmt::arg("wrap", wrap)
|
);
|
||||||
);
|
|
||||||
|
|
||||||
// modify
|
// modify
|
||||||
for (auto& f : c.fields) {
|
for (auto& f : c.fields) {
|
||||||
if (codegen::getStatus(f) != BindStatus::Unbindable) {
|
if (codegen::getStatus(f) != BindStatus::Unbindable) {
|
||||||
auto begin = f.get_fn();
|
auto begin = f.get_fn();
|
||||||
|
|
||||||
std::string function_name;
|
std::string function_name;
|
||||||
|
|
||||||
switch (begin->type) {
|
switch (begin->type) {
|
||||||
case FunctionType::Normal:
|
case FunctionType::Normal: function_name = begin->name; break;
|
||||||
function_name = begin->name;
|
case FunctionType::Ctor: function_name = "constructor"; break;
|
||||||
break;
|
case FunctionType::Dtor: function_name = "destructor"; break;
|
||||||
case FunctionType::Ctor:
|
}
|
||||||
function_name = "constructor";
|
|
||||||
break;
|
|
||||||
case FunctionType::Dtor:
|
|
||||||
function_name = "destructor";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
single_output += fmt::format(format_strings::apply_function,
|
single_output += fmt::format(
|
||||||
fmt::arg("addr_index", f.field_id),
|
format_strings::apply_function, fmt::arg("addr_index", f.field_id),
|
||||||
fmt::arg("pure_index", bank.getPure(*begin, c.name)),
|
fmt::arg("pure_index", bank.getPure(*begin, c.name)),
|
||||||
fmt::arg("class_name", c.name),
|
fmt::arg("class_name", c.name), fmt::arg("function_name", function_name),
|
||||||
fmt::arg("function_name", function_name),
|
fmt::arg("function_convention", codegen::getConvention(f))
|
||||||
fmt::arg("function_convention", codegen::getConvention(f))
|
);
|
||||||
);
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
single_output += format_strings::modify_end;
|
single_output += format_strings::modify_end;
|
||||||
|
|
||||||
writeFile(singleFolder / filename, single_output);
|
writeFile(singleFolder / filename, single_output);
|
||||||
}
|
}
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,30 +10,84 @@ namespace geode {
|
||||||
class Mod;
|
class Mod;
|
||||||
class Event;
|
class Event;
|
||||||
|
|
||||||
enum class PassThrough : bool {
|
enum class ListenerResult {
|
||||||
Propagate,
|
Propagate,
|
||||||
Stop,
|
Stop
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GEODE_DLL BasicEventHandler {
|
struct GEODE_DLL EventListenerProtocol {
|
||||||
virtual PassThrough passThrough(Event*) = 0;
|
virtual void enable();
|
||||||
|
virtual void disable();
|
||||||
|
virtual ListenerResult passThrough(Event*) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
virtual ~BasicEventHandler();
|
template <typename C, typename T>
|
||||||
|
struct to_member;
|
||||||
void listen();
|
|
||||||
void unlisten();
|
template <typename C, typename R, typename ...Args>
|
||||||
|
struct to_member<C, R(Args...)> {
|
||||||
|
using value = R(C::*)(Args...);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
concept is_event = std::is_base_of_v<Event, T>;
|
||||||
|
|
||||||
|
template <is_event T>
|
||||||
|
class EventFilter {
|
||||||
|
public:
|
||||||
|
using Callback = ListenerResult(T*);
|
||||||
|
using Event = T;
|
||||||
|
|
||||||
|
ListenerResult handle(std::function<Callback> fn, T* e) {
|
||||||
|
return fn(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
concept is_filter =
|
||||||
|
std::is_base_of_v<EventFilter<typename T::Event>, T> &&
|
||||||
|
requires(T a) {
|
||||||
|
a.handle(std::declval<typename T::Callback>(), std::declval<typename T::Event*>());
|
||||||
|
};
|
||||||
|
|
||||||
|
template <is_filter T>
|
||||||
|
class EventListener : public EventListenerProtocol {
|
||||||
|
public:
|
||||||
|
using Callback = typename T::Callback;
|
||||||
|
template <typename C> requires std::is_class_v<C>
|
||||||
|
using MemberFn = typename to_member<C, Callback>::value;
|
||||||
|
|
||||||
|
ListenerResult passThrough(Event* e) override {
|
||||||
|
if (auto myev = dynamic_cast<typename T::Event*>(e)) {
|
||||||
|
return m_filter.handle(m_callback, myev);
|
||||||
|
}
|
||||||
|
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) {}
|
||||||
|
|
||||||
|
template <class C>
|
||||||
|
EventListener(C* cls, MemberFn<C> fn, T filter = T()) : EventListener(std::bind(fn, cls, std::placeholders::_1), filter) {}
|
||||||
|
|
||||||
|
void bind(std::function<Callback> fn) {
|
||||||
|
m_callback = fn;
|
||||||
|
}
|
||||||
|
template <typename C>
|
||||||
|
void bind(C* cls, MemberFn<C> fn) {
|
||||||
|
m_callback = std::bind(fn, cls, std::placeholders::_1);
|
||||||
|
}
|
||||||
|
protected:
|
||||||
|
std::function<Callback> m_callback;
|
||||||
|
T m_filter;
|
||||||
};
|
};
|
||||||
|
|
||||||
class GEODE_DLL Event {
|
class GEODE_DLL Event {
|
||||||
static std::unordered_set<BasicEventHandler*> s_handlers;
|
static std::unordered_set<EventListenerProtocol*> s_listeners;
|
||||||
|
|
||||||
friend BasicEventHandler;
|
|
||||||
|
|
||||||
Mod* m_sender;
|
Mod* m_sender;
|
||||||
|
friend EventListenerProtocol;
|
||||||
public:
|
public:
|
||||||
static std::unordered_set<BasicEventHandler*> const& getHandlers();
|
|
||||||
|
|
||||||
void postFrom(Mod* sender);
|
void postFrom(Mod* sender);
|
||||||
|
|
||||||
inline void post() {
|
inline void post() {
|
||||||
|
@ -44,21 +98,4 @@ namespace geode {
|
||||||
|
|
||||||
virtual ~Event();
|
virtual ~Event();
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
class EventHandler : public BasicEventHandler {
|
|
||||||
public:
|
|
||||||
virtual PassThrough handle(T*) = 0;
|
|
||||||
|
|
||||||
PassThrough passThrough(Event* ev) override {
|
|
||||||
if (auto myev = dynamic_cast<T*>(ev)) {
|
|
||||||
return handle(myev);
|
|
||||||
}
|
|
||||||
return PassThrough::Propagate;
|
|
||||||
}
|
|
||||||
|
|
||||||
EventHandler() {
|
|
||||||
listen();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ namespace geode {
|
||||||
static constexpr std::string_view GEODE_CONFIG_DIRECTORY = "config";
|
static constexpr std::string_view GEODE_CONFIG_DIRECTORY = "config";
|
||||||
static constexpr std::string_view GEODE_TEMP_DIRECTORY = "temp";
|
static constexpr std::string_view GEODE_TEMP_DIRECTORY = "temp";
|
||||||
static constexpr std::string_view GEODE_MOD_EXTENSION = ".geode";
|
static constexpr std::string_view GEODE_MOD_EXTENSION = ".geode";
|
||||||
|
static constexpr std::string_view GEODE_INDEX_DIRECTORY = "index";
|
||||||
|
|
||||||
class Mod;
|
class Mod;
|
||||||
class Hook;
|
class Hook;
|
||||||
|
@ -41,7 +42,7 @@ namespace geode {
|
||||||
class VersionInfo;
|
class VersionInfo;
|
||||||
|
|
||||||
namespace modifier {
|
namespace modifier {
|
||||||
template <class, class, class>
|
template <class, class>
|
||||||
class FieldIntermediate;
|
class FieldIntermediate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -101,7 +102,7 @@ namespace geode {
|
||||||
|
|
||||||
size_t getFieldIndexForClass(size_t hash);
|
size_t getFieldIndexForClass(size_t hash);
|
||||||
|
|
||||||
template <class, class, class>
|
template <class, class>
|
||||||
friend class modifier::FieldIntermediate;
|
friend class modifier::FieldIntermediate;
|
||||||
|
|
||||||
void updateModResources(Mod* mod);
|
void updateModResources(Mod* mod);
|
||||||
|
|
|
@ -468,11 +468,19 @@ namespace geode {
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
T getBuiltInSettingValue(const std::shared_ptr<Setting> setting) {
|
T getBuiltInSettingValue(const std::shared_ptr<Setting> setting) {
|
||||||
GEODE_INT_BUILTIN_SETTING_IF(Bool, getValue(), std::is_same_v<T, bool>)
|
GEODE_INT_BUILTIN_SETTING_IF(Bool, getValue(), std::is_same_v<T, bool>)
|
||||||
else GEODE_INT_BUILTIN_SETTING_IF(Float, getValue(), std::is_floating_point_v<T>) else GEODE_INT_BUILTIN_SETTING_IF(Int, getValue(), std::is_integral_v<T>) else GEODE_INT_BUILTIN_SETTING_IF(String, getValue(), std::is_same_v<T, std::string>) else {
|
else GEODE_INT_BUILTIN_SETTING_IF(Float, getValue(), std::is_floating_point_v<T>)
|
||||||
static_assert(!std::is_same_v<T, T>, "todo: implement");
|
else GEODE_INT_BUILTIN_SETTING_IF(Int, getValue(), std::is_integral_v<T>)
|
||||||
|
else GEODE_INT_BUILTIN_SETTING_IF(String, getValue(), std::is_same_v<T, std::string>)
|
||||||
|
else GEODE_INT_BUILTIN_SETTING_IF(File, getValue(), std::is_same_v<T, ghc::filesystem::path>)
|
||||||
|
else GEODE_INT_BUILTIN_SETTING_IF(Color, getValue(), std::is_same_v<T, cocos2d::ccColor3B>)
|
||||||
|
else GEODE_INT_BUILTIN_SETTING_IF(ColorAlpha, getValue(), std::is_same_v<T, cocos2d::ccColor4B>)
|
||||||
|
else {
|
||||||
|
static_assert(!std::is_same_v<T, T>, "Unsupported type for getting setting value!");
|
||||||
}
|
}
|
||||||
return T();
|
return T();
|
||||||
}
|
}
|
||||||
|
@ -480,10 +488,17 @@ namespace geode {
|
||||||
template <class T>
|
template <class T>
|
||||||
void setBuiltInSettingValue(const std::shared_ptr<Setting> setting, T const& value) {
|
void setBuiltInSettingValue(const std::shared_ptr<Setting> setting, T const& value) {
|
||||||
GEODE_INT_BUILTIN_SETTING_IF(Bool, setValue(value), std::is_same_v<T, bool>)
|
GEODE_INT_BUILTIN_SETTING_IF(Bool, setValue(value), std::is_same_v<T, bool>)
|
||||||
else GEODE_INT_BUILTIN_SETTING_IF(Float, setValue(value), std::is_floating_point_v<T>) else GEODE_INT_BUILTIN_SETTING_IF(Int, setValue(value), std::is_integral_v<T>) else GEODE_INT_BUILTIN_SETTING_IF(String, setValue(value), std::is_same_v<T, std::string>) else {
|
else GEODE_INT_BUILTIN_SETTING_IF(Float, setValue(value), std::is_floating_point_v<T>)
|
||||||
static_assert(!std::is_same_v<T, T>, "todo: implement");
|
else GEODE_INT_BUILTIN_SETTING_IF(Int, setValue(value), std::is_integral_v<T>)
|
||||||
|
else GEODE_INT_BUILTIN_SETTING_IF(String, setValue(value), std::is_same_v<T, std::string>)
|
||||||
|
else GEODE_INT_BUILTIN_SETTING_IF(File, setValue(value), std::is_same_v<T, ghc::filesystem::path>)
|
||||||
|
else GEODE_INT_BUILTIN_SETTING_IF(Color, setValue(value), std::is_same_v<T, cocos2d::ccColor3B>)
|
||||||
|
else GEODE_INT_BUILTIN_SETTING_IF(ColorAlpha, setValue(value), std::is_same_v<T, cocos2d::ccColor4B>)
|
||||||
|
else {
|
||||||
|
static_assert(!std::is_same_v<T, T>, "Unsupported type for getting setting value!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// clang-format on
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
|
|
|
@ -18,41 +18,37 @@ namespace geode {
|
||||||
std::shared_ptr<Setting> getSetting() const;
|
std::shared_ptr<Setting> getSetting() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T>
|
template <typename T = Setting, typename = std::enable_if_t<std::is_base_of_v<Setting, T>>>
|
||||||
class SettingChangedEventHandler : public EventHandler<SettingChangedEvent> {
|
class SettingChangedFilter : public EventFilter<SettingChangedEvent> {
|
||||||
public:
|
public:
|
||||||
using Consumer = void (*)(std::shared_ptr<T>);
|
using Callback = void(std::shared_ptr<T>);
|
||||||
|
using Event = SettingChangedEvent;
|
||||||
|
|
||||||
static_assert(std::is_base_of_v<Setting, T>, "Setting must inherit from the Setting class");
|
ListenerResult handle(std::function<Callback> fn, SettingChangedEvent* event) {
|
||||||
|
|
||||||
protected:
|
|
||||||
Consumer m_consumer;
|
|
||||||
std::string m_modID;
|
|
||||||
std::optional<std::string> m_targetKey;
|
|
||||||
|
|
||||||
public:
|
|
||||||
PassThrough handle(SettingChangedEvent* event) override {
|
|
||||||
if (m_modID == event->getModID() &&
|
if (m_modID == event->getModID() &&
|
||||||
(!m_targetKey || m_targetKey.value() == event->getSetting()->getKey())) {
|
(!m_targetKey || m_targetKey.value() == event->getSetting()->getKey())) {
|
||||||
m_consumer(std::static_pointer_cast<T>(event->getSetting()));
|
fn(std::static_pointer_cast<T>(event->getSetting()));
|
||||||
}
|
}
|
||||||
return PassThrough::Propagate;
|
return ListenerResult::Propagate;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listen to changes on a specific setting
|
* Listen to changes on a specific setting
|
||||||
*/
|
*/
|
||||||
SettingChangedEventHandler(
|
SettingChangedFilter(
|
||||||
std::string const& modID, std::string const& settingID, Consumer handler
|
std::string const& modID, std::string const& settingID
|
||||||
) :
|
) :
|
||||||
m_modID(modID),
|
m_modID(modID),
|
||||||
m_targetKey(settingID), m_consumer(handler) {}
|
m_targetKey(settingID) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listen to changes on all of a mods' settings
|
* Listen to changes on all of a mods' settings
|
||||||
*/
|
*/
|
||||||
SettingChangedEventHandler(std::string const& modID, Consumer handler) :
|
SettingChangedFilter(std::string const& modID) :
|
||||||
m_modID(modID), m_targetKey(std::nullopt), m_consumer(handler) {}
|
m_modID(modID), m_targetKey(std::nullopt) {}
|
||||||
|
protected:
|
||||||
|
std::string m_modID;
|
||||||
|
std::optional<std::string> m_targetKey;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
|
@ -61,14 +57,14 @@ namespace geode {
|
||||||
std::string const& settingID, void (*callback)(std::shared_ptr<T>)
|
std::string const& settingID, void (*callback)(std::shared_ptr<T>)
|
||||||
) {
|
) {
|
||||||
Loader::get()->scheduleOnModLoad(getMod(), [=]() {
|
Loader::get()->scheduleOnModLoad(getMod(), [=]() {
|
||||||
static SettingChangedEventHandler<T> _(getMod()->getID(), settingID, callback);
|
static auto _ = EventListener(callback, SettingChangedFilter<T>(getMod()->getID(), settingID));
|
||||||
});
|
});
|
||||||
return std::monostate();
|
return std::monostate();
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::monostate listenForAllSettingChanges(void (*callback)(std::shared_ptr<Setting>)) {
|
static std::monostate listenForAllSettingChanges(void (*callback)(std::shared_ptr<Setting>)) {
|
||||||
Loader::get()->scheduleOnModLoad(getMod(), [=]() {
|
Loader::get()->scheduleOnModLoad(getMod(), [=]() {
|
||||||
static SettingChangedEventHandler<Setting> _(getMod()->getID(), callback);
|
static auto _ = EventListener(callback, SettingChangedFilter(getMod()->getID()));
|
||||||
});
|
});
|
||||||
return std::monostate();
|
return std::monostate();
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ namespace geode::modifier {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class Base, class Intermediate, class Parent>
|
template <class Parent, class Base>
|
||||||
class FieldIntermediate {
|
class FieldIntermediate {
|
||||||
// Padding used for guaranteeing any member of parents
|
// Padding used for guaranteeing any member of parents
|
||||||
// will be in between sizeof(Intermediate) and sizeof(Parent)
|
// will be in between sizeof(Intermediate) and sizeof(Parent)
|
||||||
|
@ -54,22 +54,22 @@ namespace geode::modifier {
|
||||||
|
|
||||||
auto parent = new (parentContainer.data()) Parent();
|
auto parent = new (parentContainer.data()) Parent();
|
||||||
|
|
||||||
parent->Intermediate::~Intermediate();
|
parent->Base::~Base();
|
||||||
|
|
||||||
std::memcpy(
|
std::memcpy(
|
||||||
offsetField, std::launder(&parentContainer[sizeof(Intermediate)]),
|
offsetField, std::launder(&parentContainer[sizeof(Base)]),
|
||||||
sizeof(Parent) - sizeof(Intermediate)
|
sizeof(Parent) - sizeof(Base)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fieldDestructor(void* offsetField) {
|
static void fieldDestructor(void* offsetField) {
|
||||||
std::array<std::byte, sizeof(Parent)> parentContainer;
|
std::array<std::byte, sizeof(Parent)> parentContainer;
|
||||||
|
|
||||||
auto parent = new (parentContainer.data()) Intermediate();
|
auto parent = new (parentContainer.data()) Base();
|
||||||
|
|
||||||
std::memcpy(
|
std::memcpy(
|
||||||
std::launder(&parentContainer[sizeof(Intermediate)]), offsetField,
|
std::launder(&parentContainer[sizeof(Base)]), offsetField,
|
||||||
sizeof(Parent) - sizeof(Intermediate)
|
sizeof(Parent) - sizeof(Base)
|
||||||
);
|
);
|
||||||
|
|
||||||
static_cast<Parent*>(parent)->Parent::~Parent();
|
static_cast<Parent*>(parent)->Parent::~Parent();
|
||||||
|
@ -87,15 +87,14 @@ namespace geode::modifier {
|
||||||
auto offsetField = container->getField(index);
|
auto offsetField = container->getField(index);
|
||||||
if (!offsetField) {
|
if (!offsetField) {
|
||||||
offsetField = container->setField(
|
offsetField = container->setField(
|
||||||
index, sizeof(Parent) - sizeof(Intermediate),
|
index, sizeof(Parent) - sizeof(Base), &FieldIntermediate::fieldDestructor
|
||||||
&FieldIntermediate::fieldDestructor
|
|
||||||
);
|
);
|
||||||
|
|
||||||
FieldIntermediate::fieldConstructor(offsetField);
|
FieldIntermediate::fieldConstructor(offsetField);
|
||||||
}
|
}
|
||||||
|
|
||||||
return reinterpret_cast<Parent*>(
|
return reinterpret_cast<Parent*>(
|
||||||
reinterpret_cast<std::byte*>(offsetField) - sizeof(Intermediate)
|
reinterpret_cast<std::byte*>(offsetField) - sizeof(Base)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,15 +8,9 @@
|
||||||
* struct hook0 {};
|
* struct hook0 {};
|
||||||
* namespace {
|
* namespace {
|
||||||
* struct hook0Parent {};
|
* struct hook0Parent {};
|
||||||
* Modify<hook0<hook0Parent>, MenuLayer> hook0Apply;
|
|
||||||
* struct GEODE_HIDDEN hook0Intermediate: public MenuLayer {
|
|
||||||
* geode::modifier::FieldIntermediate<MenuLayer,
|
|
||||||
* hook0<hook0Intermediate>, hook0<hook0Parent>
|
|
||||||
* > m_fields;
|
|
||||||
* };
|
|
||||||
* }
|
* }
|
||||||
* template<>
|
* template<>
|
||||||
* struct GEODE_HIDDEN hook0<hook0Parent>: hook0Intermediate {
|
* struct GEODE_HIDDEN hook0<hook0Parent> : Modify<hook0<hook0Parent>, MenuLayer> {
|
||||||
* // code stuff idk
|
* // code stuff idk
|
||||||
* };
|
* };
|
||||||
*
|
*
|
||||||
|
@ -24,33 +18,19 @@
|
||||||
* I am bad at this stuff
|
* I am bad at this stuff
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define GEODE_MODIFY_DECLARE_ANONYMOUS(base, derived) \
|
#define GEODE_MODIFY_DECLARE_ANONYMOUS(base, derived) \
|
||||||
derived##Dummy; \
|
derived##Dummy; \
|
||||||
template <class> \
|
template <class> \
|
||||||
struct derived {}; \
|
struct derived {}; \
|
||||||
namespace { \
|
namespace { \
|
||||||
struct derived##Parent {}; \
|
struct derived##Parent {}; \
|
||||||
Modify<derived<derived##Parent>, base> derived##Apply; \
|
} \
|
||||||
struct GEODE_HIDDEN derived##Intermediate : base { \
|
template <> \
|
||||||
mutable geode::modifier::FieldIntermediate< \
|
struct GEODE_HIDDEN derived<derived##Parent> : geode::Modify<derived<derived##Parent>, base>
|
||||||
base, derived##Intermediate, derived<derived##Parent>> \
|
|
||||||
m_fields; \
|
|
||||||
}; \
|
|
||||||
} \
|
|
||||||
template <> \
|
|
||||||
struct GEODE_HIDDEN derived<derived##Parent> : derived##Intermediate
|
|
||||||
|
|
||||||
#define GEODE_MODIFY_DECLARE(base, derived) \
|
#define GEODE_MODIFY_DECLARE(base, derived) \
|
||||||
derived##Dummy; \
|
derived##Dummy; \
|
||||||
struct derived; \
|
struct GEODE_HIDDEN derived : geode::Modify<derived, base>
|
||||||
namespace { \
|
|
||||||
Modify<derived, base> derived##Apply; \
|
|
||||||
struct GEODE_HIDDEN derived##Intermediate : base { \
|
|
||||||
mutable geode::modifier::FieldIntermediate<base, derived##Intermediate, derived> \
|
|
||||||
m_fields; \
|
|
||||||
}; \
|
|
||||||
} \
|
|
||||||
struct GEODE_HIDDEN derived : derived##Intermediate
|
|
||||||
|
|
||||||
#define GEODE_MODIFY_REDIRECT4(base, derived) GEODE_MODIFY_DECLARE(base, derived)
|
#define GEODE_MODIFY_REDIRECT4(base, derived) GEODE_MODIFY_DECLARE(base, derived)
|
||||||
#define GEODE_MODIFY_REDIRECT3(base, derived) GEODE_MODIFY_DECLARE_ANONYMOUS(base, derived)
|
#define GEODE_MODIFY_REDIRECT3(base, derived) GEODE_MODIFY_DECLARE_ANONYMOUS(base, derived)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "../meta/meta.hpp"
|
#include "../meta/meta.hpp"
|
||||||
#include "Addresses.hpp"
|
#include "Addresses.hpp"
|
||||||
|
#include "Field.hpp"
|
||||||
#include "Types.hpp"
|
#include "Types.hpp"
|
||||||
#include "Wrapper.hpp"
|
#include "Wrapper.hpp"
|
||||||
|
|
||||||
|
@ -22,7 +23,7 @@
|
||||||
namespace geode::modifier {
|
namespace geode::modifier {
|
||||||
|
|
||||||
template <class Derived, class Base>
|
template <class Derived, class Base>
|
||||||
class Modify;
|
class ModifyDerive;
|
||||||
|
|
||||||
template <class Derived>
|
template <class Derived>
|
||||||
class ModifyBase {
|
class ModifyBase {
|
||||||
|
@ -34,15 +35,29 @@ namespace geode::modifier {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
template <class, class>
|
template <class, class>
|
||||||
friend class Modify;
|
friend class ModifyDerive;
|
||||||
// explicit Modify(Property property) idea
|
// explicit Modify(Property property) idea
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class Derived, class Base>
|
template <class Derived, class Base>
|
||||||
class Modify {
|
class ModifyDerive {
|
||||||
public:
|
public:
|
||||||
Modify() {
|
ModifyDerive() {
|
||||||
static_assert(core::meta::always_false<Derived>, "Custom Modify not implemented.");
|
static_assert(core::meta::always_false<Derived>, "Custom Modify not implemented.");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace geode {
|
||||||
|
|
||||||
|
template <class Derived, class Base>
|
||||||
|
class Modify : public Base {
|
||||||
|
private:
|
||||||
|
static inline modifier::ModifyDerive<Derived, Base> s_apply;
|
||||||
|
// because for some reason we need it
|
||||||
|
static inline auto s_applyRef = &Modify::s_apply;
|
||||||
|
|
||||||
|
public:
|
||||||
|
modifier::FieldIntermediate<Derived, Base> m_fields;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -101,9 +101,32 @@ namespace geode {
|
||||||
bool operator==(T* other) const {
|
bool operator==(T* other) const {
|
||||||
return m_obj == other;
|
return m_obj == other;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(Ref<T> const& other) const {
|
bool operator==(Ref<T> const& other) const {
|
||||||
return m_obj == other.m_obj;
|
return m_obj == other.m_obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool operator!=(T* other) const {
|
||||||
|
return m_obj != other;
|
||||||
|
}
|
||||||
|
bool operator!=(Ref<T> const& other) const {
|
||||||
|
return m_obj != other.m_obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
// for containers
|
||||||
|
bool operator<(Ref<T> const& other) const {
|
||||||
|
return m_obj < other.m_obj;
|
||||||
|
}
|
||||||
|
bool operator>(Ref<T> const& other) const {
|
||||||
|
return m_obj > other.m_obj;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace std {
|
||||||
|
template<class T>
|
||||||
|
struct hash<geode::Ref<T>> {
|
||||||
|
size_t operator()(geode::Ref<T> const& ref) const {
|
||||||
|
return std::hash<T*>()(ref.data());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,4 +60,9 @@ namespace geode {
|
||||||
|
|
||||||
std::string toString() const;
|
std::string toString() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline std::ostream& operator<<(std::ostream& stream, VersionInfo const& version) {
|
||||||
|
stream << version.toString();
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ namespace geode::cast {
|
||||||
/**
|
/**
|
||||||
* Alias for static_cast
|
* Alias for static_cast
|
||||||
*/
|
*/
|
||||||
template <typename T, typename F>
|
template <class T, class F>
|
||||||
static constexpr T as(F const v) {
|
static constexpr T as(F const v) {
|
||||||
return static_cast<T>(v);
|
return static_cast<T>(v);
|
||||||
}
|
}
|
||||||
|
@ -18,8 +18,8 @@ namespace geode::cast {
|
||||||
* Cast from anything to anything else,
|
* Cast from anything to anything else,
|
||||||
* provided they are the same size
|
* provided they are the same size
|
||||||
*/
|
*/
|
||||||
template <typename T, typename F>
|
template <class T, class F>
|
||||||
static constexpr T union_cast(F v) {
|
static constexpr T union_cast(F const v) {
|
||||||
static_assert(sizeof(F) == sizeof(T), "union_cast: R and T don't match in size!");
|
static_assert(sizeof(F) == sizeof(T), "union_cast: R and T don't match in size!");
|
||||||
|
|
||||||
union {
|
union {
|
||||||
|
@ -36,27 +36,40 @@ namespace geode::cast {
|
||||||
* cast but uses reference syntactic sugar to
|
* cast but uses reference syntactic sugar to
|
||||||
* look cleaner.
|
* look cleaner.
|
||||||
*/
|
*/
|
||||||
template <typename T, typename F>
|
template <class T, class F>
|
||||||
static constexpr T reference_cast(F v) {
|
static constexpr T reference_cast(F v) {
|
||||||
return reinterpret_cast<T&>(v);
|
return reinterpret_cast<T&>(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cast an adjusted this pointer to it's base pointer
|
* Cast based on RTTI. Casts an adjusted this pointer
|
||||||
|
* to it's non offset form.
|
||||||
*/
|
*/
|
||||||
template <typename T, typename F>
|
template <class T, class F>
|
||||||
static constexpr T base_cast(F obj) {
|
static constexpr T base_cast(F const obj) {
|
||||||
return reinterpret_cast<T>(dynamic_cast<void*>(obj));
|
return static_cast<T>(dynamic_cast<void*>(obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cast based on RTTI. This is a replacement for
|
* Cast based on RTTI. This is used to check
|
||||||
* dynamic_cast, since it doesn't work for gd.
|
* if an object is exactly the class needed. Returns
|
||||||
|
* nullptr on failure.
|
||||||
*/
|
*/
|
||||||
template <typename T, typename F>
|
template <class T, class F>
|
||||||
static T typeid_cast(F obj) {
|
static T exact_cast(F const obj) {
|
||||||
if (std::string(typeid(*obj).name()) == typeid(std::remove_pointer_t<T>).name())
|
if (std::strcmp(typeid(*obj).name(), typeid(std::remove_pointer_t<T>).name()) == 0) {
|
||||||
return reinterpret_cast<T>(obj);
|
return base_cast<T>(obj);
|
||||||
else return nullptr;
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cast based on RTTI. This behaves as a replacement
|
||||||
|
* of dynamic_cast for cocos and gd classes,
|
||||||
|
* and must be used for expected results.
|
||||||
|
*/
|
||||||
|
template <class T, class F>
|
||||||
|
static T safe_cast(F const obj) {
|
||||||
|
return typeinfo_cast<T>(obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,6 +86,7 @@ namespace geode::utils::web {
|
||||||
mutable std::mutex m_mutex;
|
mutable std::mutex m_mutex;
|
||||||
std::variant<std::monostate, std::ostream*, ghc::filesystem::path> m_target =
|
std::variant<std::monostate, std::ostream*, ghc::filesystem::path> m_target =
|
||||||
std::monostate();
|
std::monostate();
|
||||||
|
std::vector<std::string> m_httpHeaders;
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
friend class AsyncWebResult;
|
friend class AsyncWebResult;
|
||||||
|
@ -134,6 +135,7 @@ namespace geode::utils::web {
|
||||||
AsyncCancelled m_cancelled = nullptr;
|
AsyncCancelled m_cancelled = nullptr;
|
||||||
bool m_sent = false;
|
bool m_sent = false;
|
||||||
std::variant<std::monostate, std::ostream*, ghc::filesystem::path> m_target;
|
std::variant<std::monostate, std::ostream*, ghc::filesystem::path> m_target;
|
||||||
|
std::vector<std::string> m_httpHeaders;
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
friend class AsyncWebResult;
|
friend class AsyncWebResult;
|
||||||
|
@ -159,6 +161,12 @@ namespace geode::utils::web {
|
||||||
* @returns Same AsyncWebRequest
|
* @returns Same AsyncWebRequest
|
||||||
*/
|
*/
|
||||||
AsyncWebRequest& join(std::string const& requestID);
|
AsyncWebRequest& join(std::string const& requestID);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In order to specify a http header to the request, give it here.
|
||||||
|
* Can be called more than once.
|
||||||
|
*/
|
||||||
|
AsyncWebRequest& header(std::string const& header);
|
||||||
/**
|
/**
|
||||||
* URL to fetch from the internet asynchronously
|
* URL to fetch from the internet asynchronously
|
||||||
* @param url URL of the data to download. Redirects will be
|
* @param url URL of the data to download. Redirects will be
|
||||||
|
|
|
@ -28,6 +28,15 @@ namespace geode {
|
||||||
return rect;
|
return rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static cocos2d::CCRect operator*(cocos2d::CCRect const& rect, float mul) {
|
||||||
|
return {
|
||||||
|
rect.origin.x * mul,
|
||||||
|
rect.origin.y * mul,
|
||||||
|
rect.size.width * mul,
|
||||||
|
rect.size.height * mul,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
static cocos2d::CCPoint operator/=(cocos2d::CCPoint& pos, float div) {
|
static cocos2d::CCPoint operator/=(cocos2d::CCPoint& pos, float div) {
|
||||||
pos.x /= div;
|
pos.x /= div;
|
||||||
pos.y /= div;
|
pos.y /= div;
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#undef min
|
||||||
|
#undef max
|
||||||
|
|
||||||
namespace geode::utils::ranges {
|
namespace geode::utils::ranges {
|
||||||
template <class C>
|
template <class C>
|
||||||
concept ValidConstContainer = requires(C const& c) {
|
concept ValidConstContainer = requires(C const& c) {
|
||||||
|
@ -205,4 +208,57 @@ namespace geode::utils::ranges {
|
||||||
std::transform(from.begin(), from.end(), res.end(), mapper);
|
std::transform(from.begin(), from.end(), res.end(), mapper);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <ValidConstContainer C>
|
||||||
|
typename C::value_type min(C const& container) {
|
||||||
|
auto it = std::min_element(container.begin(), container.end());
|
||||||
|
if (it == container.end()) {
|
||||||
|
return C::value_type();
|
||||||
|
}
|
||||||
|
return *it;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T, ValidConstContainer C, ValidIntoConverter<typename C::value_type, T> Member>
|
||||||
|
requires requires(T a, T b) {
|
||||||
|
a < b;
|
||||||
|
}
|
||||||
|
T min(C const& container, Member member) {
|
||||||
|
auto it = std::min_element(
|
||||||
|
container.begin(), container.end(),
|
||||||
|
[member](auto const& a, auto const& b) -> bool {
|
||||||
|
return member(a) < member(b);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (it == container.end()) {
|
||||||
|
return T();
|
||||||
|
}
|
||||||
|
return member(*it);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <ValidConstContainer C>
|
||||||
|
typename C::value_type max(C const& container) {
|
||||||
|
auto it = std::max_element(container.begin(), container.end());
|
||||||
|
if (it == container.end()) {
|
||||||
|
return C::value_type();
|
||||||
|
}
|
||||||
|
return *it;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T, ValidConstContainer C, ValidIntoConverter<typename C::value_type, T> Member>
|
||||||
|
requires requires(T a, T b) {
|
||||||
|
a < b;
|
||||||
|
T();
|
||||||
|
}
|
||||||
|
T max(C const& container, Member member) {
|
||||||
|
auto it = std::max_element(
|
||||||
|
container.begin(), container.end(),
|
||||||
|
[member](auto const& a, auto const& b) -> bool {
|
||||||
|
return member(a) < member(b);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (it == container.end()) {
|
||||||
|
return T();
|
||||||
|
}
|
||||||
|
return member(*it);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"geode": "v@PROJECT_VERSION@",
|
"geode": "@PROJECT_VERSION@",
|
||||||
"id": "geode.loader",
|
"id": "geode.loader",
|
||||||
"version": "v@PROJECT_VERSION@",
|
"version": "@PROJECT_VERSION@",
|
||||||
"name": "Geode",
|
"name": "Geode",
|
||||||
"developer": "Geode Team",
|
"developer": "Geode Team",
|
||||||
"description": "The Geode mod loader",
|
"description": "The Geode mod loader",
|
||||||
|
|
|
@ -68,7 +68,7 @@ public:
|
||||||
// proxy forwards
|
// proxy forwards
|
||||||
// clang-format off
|
// clang-format off
|
||||||
#include <Geode/modify/CCNode.hpp>
|
#include <Geode/modify/CCNode.hpp>
|
||||||
class $modify(ProxyCCNode, CCNode) {
|
struct ProxyCCNode : Modify<ProxyCCNode, CCNode> {
|
||||||
virtual CCObject* getUserObject() {
|
virtual CCObject* getUserObject() {
|
||||||
return GeodeNodeMetadata::set(this)->m_userObject;
|
return GeodeNodeMetadata::set(this)->m_userObject;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,9 +9,10 @@
|
||||||
USE_GEODE_NAMESPACE();
|
USE_GEODE_NAMESPACE();
|
||||||
|
|
||||||
#pragma warning(disable : 4217)
|
#pragma warning(disable : 4217)
|
||||||
template <class T = CCNode>
|
|
||||||
|
|
||||||
requires std::is_base_of_v<CCNode, T> T* setIDSafe(CCNode* node, int index, char const* id) {
|
template <class T = CCNode>
|
||||||
|
requires std::is_base_of_v<CCNode, T>
|
||||||
|
T* setIDSafe(CCNode* node, int index, char const* id) {
|
||||||
if constexpr (std::is_same_v<CCNode, T>) {
|
if constexpr (std::is_same_v<CCNode, T>) {
|
||||||
if (auto child = getChild(node, index)) {
|
if (auto child = getChild(node, index)) {
|
||||||
child->setID(id);
|
child->setID(id);
|
||||||
|
@ -29,7 +30,7 @@ requires std::is_base_of_v<CCNode, T> T* setIDSafe(CCNode* node, int index, char
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
#include <Geode/modify/LevelSearchLayer.hpp>
|
#include <Geode/modify/LevelSearchLayer.hpp>
|
||||||
class $modify(LevelSearchLayer) {
|
struct LevelSearchLayerIDs : Modify<LevelSearchLayerIDs, LevelSearchLayer> {
|
||||||
bool init() {
|
bool init() {
|
||||||
if (!LevelSearchLayer::init())
|
if (!LevelSearchLayer::init())
|
||||||
return false;
|
return false;
|
||||||
|
@ -99,4 +100,5 @@ class $modify(LevelSearchLayer) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
|
@ -3,26 +3,23 @@
|
||||||
|
|
||||||
USE_GEODE_NAMESPACE();
|
USE_GEODE_NAMESPACE();
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
#include <Geode/modify/LoadingLayer.hpp>
|
#include <Geode/modify/LoadingLayer.hpp>
|
||||||
class $modify(CustomLoadingLayer, LoadingLayer) {
|
|
||||||
|
struct CustomLoadingLayer : Modify<CustomLoadingLayer, LoadingLayer> {
|
||||||
bool m_updatingResources;
|
bool m_updatingResources;
|
||||||
|
|
||||||
CustomLoadingLayer() : m_updatingResources(false) {}
|
CustomLoadingLayer() : m_updatingResources(false) {}
|
||||||
|
|
||||||
bool init(bool fromReload) {
|
bool init(bool fromReload) {
|
||||||
if (!LoadingLayer::init(fromReload))
|
if (!LoadingLayer::init(fromReload)) return false;
|
||||||
return false;
|
|
||||||
|
|
||||||
auto winSize = CCDirector::sharedDirector()->getWinSize();
|
auto winSize = CCDirector::sharedDirector()->getWinSize();
|
||||||
|
|
||||||
auto count = Loader::get()->getAllMods().size();
|
auto count = Loader::get()->getAllMods().size();
|
||||||
|
|
||||||
auto label = CCLabelBMFont::create(
|
auto label = CCLabelBMFont::create(
|
||||||
CCString::createWithFormat(
|
CCString::createWithFormat("Geode: Loaded %lu mods", static_cast<unsigned long>(count))
|
||||||
"Geode: Loaded %lu mods",
|
->getCString(),
|
||||||
static_cast<unsigned long>(count)
|
|
||||||
)->getCString(),
|
|
||||||
"goldFont.fnt"
|
"goldFont.fnt"
|
||||||
);
|
);
|
||||||
label->setPosition(winSize.width / 2, 30.f);
|
label->setPosition(winSize.width / 2, 30.f);
|
||||||
|
@ -31,13 +28,10 @@ class $modify(CustomLoadingLayer, LoadingLayer) {
|
||||||
this->addChild(label);
|
this->addChild(label);
|
||||||
|
|
||||||
// verify loader resources
|
// verify loader resources
|
||||||
if (!InternalLoader::get()->verifyLoaderResources(
|
if (!InternalLoader::get()->verifyLoaderResources(std::bind(
|
||||||
std::bind(
|
&CustomLoadingLayer::updateResourcesProgress, this, std::placeholders::_1,
|
||||||
&CustomLoadingLayer::updateResourcesProgress, this,
|
std::placeholders::_2, std::placeholders::_3
|
||||||
std::placeholders::_1, std::placeholders::_2,
|
))) {
|
||||||
std::placeholders::_3
|
|
||||||
)
|
|
||||||
)) {
|
|
||||||
// auto bg = CCScale9Sprite::create(
|
// auto bg = CCScale9Sprite::create(
|
||||||
// "square02b_001.png", { 0.0f, 0.0f, 80.0f, 80.0f }
|
// "square02b_001.png", { 0.0f, 0.0f, 80.0f, 80.0f }
|
||||||
// );
|
// );
|
||||||
|
@ -73,17 +67,10 @@ class $modify(CustomLoadingLayer, LoadingLayer) {
|
||||||
// );
|
// );
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateResourcesProgress(
|
void updateResourcesProgress(UpdateStatus status, std::string const& info, uint8_t progress) {
|
||||||
UpdateStatus status,
|
|
||||||
std::string const& info,
|
|
||||||
uint8_t progress
|
|
||||||
) {
|
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case UpdateStatus::Progress: {
|
case UpdateStatus::Progress: {
|
||||||
this->setUpdateText(
|
this->setUpdateText("Downloading Resources: " + std::to_string(progress) + "%");
|
||||||
"Downloading Resources: " +
|
|
||||||
std::to_string(progress) + "%"
|
|
||||||
);
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case UpdateStatus::Finished: {
|
case UpdateStatus::Finished: {
|
||||||
|
@ -95,9 +82,10 @@ class $modify(CustomLoadingLayer, LoadingLayer) {
|
||||||
case UpdateStatus::Failed: {
|
case UpdateStatus::Failed: {
|
||||||
InternalLoader::platformMessageBox(
|
InternalLoader::platformMessageBox(
|
||||||
"Error updating resources",
|
"Error updating resources",
|
||||||
"Unable to update Geode resources: " + info + ".\n"
|
"Unable to update Geode resources: " + info +
|
||||||
"The game will be loaded as normal, but please be aware "
|
".\n"
|
||||||
"that it may very likely crash."
|
"The game will be loaded as normal, but please be aware "
|
||||||
|
"that it may very likely crash."
|
||||||
);
|
);
|
||||||
this->setUpdateText("Resource Download Failed");
|
this->setUpdateText("Resource Download Failed");
|
||||||
m_fields->m_updatingResources = false;
|
m_fields->m_updatingResources = false;
|
||||||
|
@ -106,12 +94,10 @@ class $modify(CustomLoadingLayer, LoadingLayer) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadAssets() {
|
void loadAssets() {
|
||||||
if (m_fields->m_updatingResources) {
|
if (m_fields->m_updatingResources) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LoadingLayer::loadAssets();
|
LoadingLayer::loadAssets();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// clang-format on
|
|
|
@ -64,7 +64,7 @@ static void updateIndexProgress(UpdateStatus status, std::string const& info, ui
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <Geode/modify/MenuLayer.hpp>
|
#include <Geode/modify/MenuLayer.hpp>
|
||||||
class $modify(CustomMenuLayer, MenuLayer) {
|
class CustomMenuLayer : Modify<CustomMenuLayer, MenuLayer> {
|
||||||
void destructor() {
|
void destructor() {
|
||||||
g_geodeButton = nullptr;
|
g_geodeButton = nullptr;
|
||||||
MenuLayer::~MenuLayer();
|
MenuLayer::~MenuLayer();
|
||||||
|
@ -160,4 +160,3 @@ class $modify(CustomMenuLayer, MenuLayer) {
|
||||||
ModListLayer::scene();
|
ModListLayer::scene();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// clang-format on
|
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
USE_GEODE_NAMESPACE();
|
USE_GEODE_NAMESPACE();
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
#include <Geode/modify/CCTouchDispatcher.hpp>
|
#include <Geode/modify/CCTouchDispatcher.hpp>
|
||||||
class $modify(CCTouchDispatcher) {
|
|
||||||
void addTargetedDelegate(CCTouchDelegate *delegate, int priority, bool swallowsTouches) {
|
struct ForcePrioRevert : Modify<ForcePrioRevert, CCTouchDispatcher> {
|
||||||
|
void addTargetedDelegate(CCTouchDelegate* delegate, int priority, bool swallowsTouches) {
|
||||||
m_bForcePrio = false;
|
m_bForcePrio = false;
|
||||||
if (m_pTargetedHandlers->count() > 0) {
|
if (m_pTargetedHandlers->count() > 0) {
|
||||||
auto handler = static_cast<CCTouchHandler*>(m_pTargetedHandlers->objectAtIndex(0));
|
auto handler = static_cast<CCTouchHandler*>(m_pTargetedHandlers->objectAtIndex(0));
|
||||||
priority = handler->getPriority() - 2;
|
priority = handler->getPriority() - 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
CCTouchDispatcher::addTargetedDelegate(delegate, priority, swallowsTouches);
|
CCTouchDispatcher::addTargetedDelegate(delegate, priority, swallowsTouches);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,4 +21,3 @@ class $modify(CCTouchDispatcher) {
|
||||||
m_bForcePrio = false;
|
m_bForcePrio = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// clang-format on
|
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
// this is the fix for the dynamic_cast problems
|
// this is the fix for the dynamic_cast problems
|
||||||
// TODO: completely replace dynamic_cast on macos
|
// TODO: completely replace dynamic_cast on macos
|
||||||
|
#include <Geode/DefaultInclude.hpp>
|
||||||
using namespace cocos2d;
|
|
||||||
using namespace geode::modifier;
|
|
||||||
|
|
||||||
#if defined(GEODE_IS_IOS) || defined(GEODE_IS_MACOS)
|
#if defined(GEODE_IS_IOS) || defined(GEODE_IS_MACOS)
|
||||||
using namespace geode::cast;
|
USE_GEODE_NAMESPACE();
|
||||||
|
|
||||||
#define HandlerFixFor(CCUtility) \
|
#define HandlerFixFor(CCUtility) \
|
||||||
class $modify(CCUtility##HandlerTypeinfoFix, CCUtility##Handler) { \
|
struct CCUtility##HandlerFix : Modify<CCUtility##HandlerFix, CCUtility##Handler> { \
|
||||||
void destructor() { \
|
void destructor() { \
|
||||||
if (m_pDelegate) { \
|
if (m_pDelegate) { \
|
||||||
cocos2d::CCObject* pObject = base_cast<cocos2d::CCObject*>(m_pDelegate); \
|
cocos2d::CCObject* pObject = base_cast<cocos2d::CCObject*>(m_pDelegate); \
|
||||||
|
@ -55,7 +53,7 @@ HandlerFixFor(CCKeyboard);
|
||||||
HandlerFixFor(CCMouse);
|
HandlerFixFor(CCMouse);
|
||||||
|
|
||||||
#include <Geode/modify/CCTargetedTouchHandler.hpp>
|
#include <Geode/modify/CCTargetedTouchHandler.hpp>
|
||||||
class $modify(CCTargetedTouchHandlerTypeinfoFix, CCTargetedTouchHandler) {
|
struct CCTargetedTouchHandlerFix : Modify<CCTargetedTouchHandlerFix, CCTargetedTouchHandler> {
|
||||||
void destructor() {
|
void destructor() {
|
||||||
if (m_pDelegate) {
|
if (m_pDelegate) {
|
||||||
cocos2d::CCObject* pObject = base_cast<cocos2d::CCObject*>(m_pDelegate);
|
cocos2d::CCObject* pObject = base_cast<cocos2d::CCObject*>(m_pDelegate);
|
||||||
|
@ -101,7 +99,7 @@ class $modify(CCTargetedTouchHandlerTypeinfoFix, CCTargetedTouchHandler) {
|
||||||
};
|
};
|
||||||
|
|
||||||
#include <Geode/modify/CCStandardTouchHandler.hpp>
|
#include <Geode/modify/CCStandardTouchHandler.hpp>
|
||||||
class $modify(CCStandardTouchHandlerTypeinfoFix, CCStandardTouchHandler) {
|
struct CCStandardTouchHandlerFix : Modify<CCStandardTouchHandlerFix, CCStandardTouchHandler> {
|
||||||
void destructor() {
|
void destructor() {
|
||||||
if (m_pDelegate) {
|
if (m_pDelegate) {
|
||||||
cocos2d::CCObject* pObject = base_cast<cocos2d::CCObject*>(m_pDelegate);
|
cocos2d::CCObject* pObject = base_cast<cocos2d::CCObject*>(m_pDelegate);
|
||||||
|
@ -140,6 +138,7 @@ class $modify(CCStandardTouchHandlerTypeinfoFix, CCStandardTouchHandler) {
|
||||||
return pHandler;
|
return pHandler;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2,12 +2,11 @@
|
||||||
|
|
||||||
USE_GEODE_NAMESPACE();
|
USE_GEODE_NAMESPACE();
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
#include <Geode/modify/AchievementNotifier.hpp>
|
#include <Geode/modify/AchievementNotifier.hpp>
|
||||||
class $modify(AchievementNotifier) {
|
|
||||||
|
struct SceneSwitch : Modify<SceneSwitch, AchievementNotifier> {
|
||||||
void willSwitchToScene(CCScene* scene) {
|
void willSwitchToScene(CCScene* scene) {
|
||||||
AchievementNotifier::willSwitchToScene(scene);
|
AchievementNotifier::willSwitchToScene(scene);
|
||||||
SceneManager::get()->willSwitchToScene(scene);
|
SceneManager::get()->willSwitchToScene(scene);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// clang-format on
|
|
|
@ -2,9 +2,9 @@
|
||||||
|
|
||||||
USE_GEODE_NAMESPACE();
|
USE_GEODE_NAMESPACE();
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
#include <Geode/modify/AppDelegate.hpp>
|
#include <Geode/modify/AppDelegate.hpp>
|
||||||
class $modify(AppDelegate) {
|
|
||||||
|
struct SaveLoader : Modify<SaveLoader, AppDelegate> {
|
||||||
void trySaveGame() {
|
void trySaveGame() {
|
||||||
log::log(Severity::Info, Loader::getInternalMod(), "Saving...");
|
log::log(Severity::Info, Loader::getInternalMod(), "Saving...");
|
||||||
|
|
||||||
|
@ -14,8 +14,7 @@ class $modify(AppDelegate) {
|
||||||
}
|
}
|
||||||
|
|
||||||
log::log(Severity::Info, Loader::getInternalMod(), "Saved");
|
log::log(Severity::Info, Loader::getInternalMod(), "Saved");
|
||||||
|
|
||||||
return AppDelegate::trySaveGame();
|
return AppDelegate::trySaveGame();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// clang-format on
|
|
|
@ -1,12 +1,12 @@
|
||||||
#include <InternalLoader.hpp>
|
#include <InternalLoader.hpp>
|
||||||
|
|
||||||
USE_GEODE_NAMESPACE();
|
USE_GEODE_NAMESPACE();
|
||||||
// clang-format off
|
|
||||||
#include <Geode/modify/CCScheduler.hpp>
|
#include <Geode/modify/CCScheduler.hpp>
|
||||||
class $modify(CCScheduler) {
|
|
||||||
|
struct FunctionQueue : Modify<FunctionQueue, CCScheduler> {
|
||||||
void update(float dt) {
|
void update(float dt) {
|
||||||
InternalLoader::get()->executeGDThreadQueue();
|
InternalLoader::get()->executeGDThreadQueue();
|
||||||
return CCScheduler::update(dt);
|
return CCScheduler::update(dt);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// clang-format on
|
|
|
@ -4,21 +4,12 @@
|
||||||
|
|
||||||
USE_GEODE_NAMESPACE();
|
USE_GEODE_NAMESPACE();
|
||||||
|
|
||||||
class $modify(GameManager) {
|
struct ResourcesUpdate : Modify<ResourcesUpdate, LoadingLayer> {
|
||||||
void reloadAllStep2() {
|
void loadAssets() {
|
||||||
GameManager::reloadAllStep2();
|
LoadingLayer::loadAssets();
|
||||||
Loader::get()->updateResourcePaths();
|
// this is in case the user refreshes texture quality at runtime
|
||||||
}
|
if (this->m_loadStep == 10) {
|
||||||
|
Loader::get()->updateResources();
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class $modify(LoadingLayer) {
|
|
||||||
bool init(bool fromReload) {
|
|
||||||
// this is in case the user refreshes texture quality at runtime
|
|
||||||
// resources are loaded first so things like texture packs override
|
|
||||||
// the GD textures
|
|
||||||
Loader::get()->waitForModsToBeLoaded();
|
|
||||||
Loader::get()->updateResources();
|
|
||||||
return LoadingLayer::init(fromReload);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// clang-format on
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include <Geode/utils/ranges.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 <fmt/format.h>
|
||||||
#include <hash.hpp>
|
#include <hash.hpp>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
|
@ -86,7 +87,7 @@ void Index::updateIndex(IndexUpdateCallback callback, bool force) {
|
||||||
|
|
||||||
// create directory for the local clone of
|
// create directory for the local clone of
|
||||||
// the index
|
// the index
|
||||||
auto indexDir = Loader::get()->getGeodeDirectory() / "index";
|
auto indexDir = Loader::get()->getGeodeSaveDirectory() / GEODE_INDEX_DIRECTORY;
|
||||||
ghc::filesystem::create_directories(indexDir);
|
ghc::filesystem::create_directories(indexDir);
|
||||||
|
|
||||||
#if GITHUB_DONT_RATE_LIMIT_ME_PLS == 1
|
#if GITHUB_DONT_RATE_LIMIT_ME_PLS == 1
|
||||||
|
@ -104,39 +105,32 @@ void Index::updateIndex(IndexUpdateCallback callback, bool force) {
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// read sha of currently installed commit
|
||||||
|
std::string currentCommitSHA = "";
|
||||||
|
if (ghc::filesystem::exists(indexDir / "current")) {
|
||||||
|
auto data = utils::file::readString(indexDir / "current");
|
||||||
|
if (data) {
|
||||||
|
currentCommitSHA = data.value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
web::AsyncWebRequest()
|
web::AsyncWebRequest()
|
||||||
.join("index-update")
|
.join("index-update")
|
||||||
.fetch("https://api.github.com/repos/geode-sdk/mods/commits")
|
.header(fmt::format("If-None-Match: \"{}\"", currentCommitSHA))
|
||||||
.json()
|
.header("Accept: application/vnd.github.sha")
|
||||||
.then([this, force, callback](nlohmann::json const& json) {
|
.fetch("https://api.github.com/repos/geode-sdk/mods/commits/main")
|
||||||
auto indexDir = Loader::get()->getGeodeDirectory() / "index";
|
.text()
|
||||||
|
.then([this, force, callback, currentCommitSHA](std::string const& upcomingCommitSHA) {
|
||||||
|
auto indexDir = Loader::get()->getGeodeSaveDirectory() / GEODE_INDEX_DIRECTORY;
|
||||||
|
|
||||||
// check if rate-limited (returns object)
|
// gee i sure hope no one does 60 commits to the mod index an hour and download every
|
||||||
JsonChecker checkerObj(json);
|
// single one of them
|
||||||
auto obj = checkerObj.root("[geode-sdk/mods/commits]").obj();
|
if (upcomingCommitSHA == "") {
|
||||||
if (obj.has("documentation_url") && obj.has("message")) {
|
m_upToDate = true;
|
||||||
RETURN_ERROR(obj.has("message").get<std::string>());
|
m_updating = false;
|
||||||
}
|
|
||||||
|
|
||||||
// get sha of latest commit
|
if (callback) callback(UpdateStatus::Finished, "", 100);
|
||||||
JsonChecker checker(json);
|
return;
|
||||||
auto root = checker.root("[geode-sdk/mods/commits]").array();
|
|
||||||
|
|
||||||
std::string upcomingCommitSHA;
|
|
||||||
if (auto first = root.at(0).obj().needs("sha")) {
|
|
||||||
upcomingCommitSHA = first.get<std::string>();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
RETURN_ERROR("Unable to get hash from latest commit: " + checker.getError());
|
|
||||||
}
|
|
||||||
|
|
||||||
// read sha of currently installed commit
|
|
||||||
std::string currentCommitSHA = "";
|
|
||||||
if (ghc::filesystem::exists(indexDir / "current")) {
|
|
||||||
auto data = utils::file::readString(indexDir / "current");
|
|
||||||
if (data) {
|
|
||||||
currentCommitSHA = data.value();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// update if forced or latest commit has
|
// update if forced or latest commit has
|
||||||
|
@ -224,16 +218,34 @@ void Index::addIndexItemFromFolder(ghc::filesystem::path const& dir) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto info = ModInfo::createFromFile(dir / "mod.json");
|
auto infoRes = ModInfo::createFromFile(dir / "mod.json");
|
||||||
if (!info) {
|
if (!infoRes) {
|
||||||
log::warn("{}: {}, skipping", dir, info.error());
|
log::warn("{}: {}, skipping", dir, infoRes.error());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
auto info = infoRes.value();
|
||||||
|
|
||||||
|
// make sure only latest version is present in index
|
||||||
|
auto old = std::find_if(m_items.begin(), m_items.end(), [info](IndexItem const& item) {
|
||||||
|
return item.m_info.m_id == info.m_id;
|
||||||
|
});
|
||||||
|
if (old != m_items.end()) {
|
||||||
|
// this one is newer
|
||||||
|
if (old->m_info.m_version < info.m_version) {
|
||||||
|
m_items.erase(old);
|
||||||
|
} else {
|
||||||
|
log::warn(
|
||||||
|
"Found older version of ({} < {}) of {}, skipping",
|
||||||
|
info.m_version, old->m_info.m_version, info.m_id
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
IndexItem item;
|
IndexItem item;
|
||||||
|
|
||||||
item.m_path = dir;
|
item.m_path = dir;
|
||||||
item.m_info = info.value();
|
item.m_info = info;
|
||||||
|
|
||||||
if (!json.contains("download") || !json["download"].is_object()) {
|
if (!json.contains("download") || !json["download"].is_object()) {
|
||||||
log::warn("[index.json].download is not an object, skipping");
|
log::warn("[index.json].download is not an object, skipping");
|
||||||
|
@ -284,7 +296,7 @@ void Index::addIndexItemFromFolder(ghc::filesystem::path const& dir) {
|
||||||
|
|
||||||
Result<> Index::updateIndexFromLocalCache() {
|
Result<> Index::updateIndexFromLocalCache() {
|
||||||
m_items.clear();
|
m_items.clear();
|
||||||
auto baseIndexDir = Loader::get()->getGeodeDirectory() / "index";
|
auto baseIndexDir = Loader::get()->getGeodeSaveDirectory() / GEODE_INDEX_DIRECTORY;
|
||||||
|
|
||||||
// load geode.json (index settings)
|
// load geode.json (index settings)
|
||||||
if (auto baseIndexJson = readJSON(baseIndexDir / "geode.json")) {
|
if (auto baseIndexJson = readJSON(baseIndexDir / "geode.json")) {
|
||||||
|
@ -529,7 +541,7 @@ void InstallItems::error(std::string const& info) {
|
||||||
|
|
||||||
void InstallItems::finish(bool replaceFiles) {
|
void InstallItems::finish(bool replaceFiles) {
|
||||||
// move files from temp dir to geode directory
|
// move files from temp dir to geode directory
|
||||||
auto tempDir = Loader::get()->getGeodeDirectory() / "index" / "temp";
|
auto tempDir = Loader::get()->getGeodeSaveDirectory() / GEODE_INDEX_DIRECTORY / "temp";
|
||||||
for (auto& file : ghc::filesystem::directory_iterator(tempDir)) {
|
for (auto& file : ghc::filesystem::directory_iterator(tempDir)) {
|
||||||
try {
|
try {
|
||||||
auto modDir = Loader::get()->getGeodeDirectory() / "mods";
|
auto modDir = Loader::get()->getGeodeDirectory() / "mods";
|
||||||
|
@ -605,7 +617,7 @@ InstallItems::CallbackID InstallItems::start(ItemInstallCallback callback, bool
|
||||||
// by virtue of running this function we know item must be valid
|
// by virtue of running this function we know item must be valid
|
||||||
auto item = Index::get()->getKnownItem(inst);
|
auto item = Index::get()->getKnownItem(inst);
|
||||||
|
|
||||||
auto indexDir = Loader::get()->getGeodeDirectory() / "index";
|
auto indexDir = Loader::get()->getGeodeSaveDirectory() / GEODE_INDEX_DIRECTORY;
|
||||||
(void)file::createDirectoryAll(indexDir / "temp");
|
(void)file::createDirectoryAll(indexDir / "temp");
|
||||||
auto tempFile = indexDir / "temp" / item.m_download.m_filename;
|
auto tempFile = indexDir / "temp" / item.m_download.m_filename;
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <Geode/loader/Log.hpp>
|
#include <Geode/loader/Log.hpp>
|
||||||
#include <Geode/utils/fetch.hpp>
|
#include <Geode/utils/fetch.hpp>
|
||||||
#include <Geode/utils/file.hpp>
|
#include <Geode/utils/file.hpp>
|
||||||
|
#include <fmt/format.h>
|
||||||
#include <hash.hpp>
|
#include <hash.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
@ -95,67 +96,38 @@ void InternalLoader::downloadLoaderResources(IndexUpdateCallback callback) {
|
||||||
|
|
||||||
web::AsyncWebRequest()
|
web::AsyncWebRequest()
|
||||||
.join("update-geode-loader-resources")
|
.join("update-geode-loader-resources")
|
||||||
.fetch("https://api.github.com/repos/geode-sdk/geode/releases/tags/" + version)
|
.fetch(fmt::format(
|
||||||
.json()
|
"https://github.com/geode-sdk/geode/releases/download/{}/resources.zip", version
|
||||||
.then([tempResourcesZip, resourcesDir, callback](nlohmann::json const& json) {
|
))
|
||||||
auto checker = JsonChecker(json);
|
.into(tempResourcesZip)
|
||||||
auto root = checker.root("[matching geode release]").obj();
|
.then([tempResourcesZip, resourcesDir, callback](auto) {
|
||||||
|
// unzip resources zip
|
||||||
// find resources.zip and download it
|
auto unzip = file::unzipTo(tempResourcesZip, resourcesDir);
|
||||||
for (auto asset : root.needs("assets").iterate()) {
|
if (!unzip) {
|
||||||
auto obj = asset.obj();
|
if (callback)
|
||||||
if (obj.needs("name").get<std::string>() == "resources.zip") {
|
callback(
|
||||||
auto url = obj.needs("browser_download_url").get<std::string>();
|
UpdateStatus::Failed, "Unable to unzip new resources: " + unzip.error(), 0
|
||||||
if (url.size()) {
|
);
|
||||||
web::AsyncWebRequest()
|
return;
|
||||||
.fetch(url)
|
}
|
||||||
.into(tempResourcesZip)
|
// delete resources zip
|
||||||
.then([tempResourcesZip, resourcesDir, callback](auto) {
|
try {
|
||||||
// unzip resources zip
|
ghc::filesystem::remove(tempResourcesZip);
|
||||||
auto unzip = file::unzipTo(tempResourcesZip, resourcesDir);
|
}
|
||||||
if (!unzip) {
|
catch (...) {
|
||||||
if (callback)
|
|
||||||
callback(
|
|
||||||
UpdateStatus::Failed,
|
|
||||||
"Unable to unzip new resources: " + unzip.error(), 0
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// delete resources zip
|
|
||||||
try {
|
|
||||||
ghc::filesystem::remove(tempResourcesZip);
|
|
||||||
}
|
|
||||||
catch (...) {
|
|
||||||
}
|
|
||||||
|
|
||||||
Loader::get()->updateResources();
|
|
||||||
|
|
||||||
if (callback) callback(
|
|
||||||
UpdateStatus::Finished,
|
|
||||||
"Resources updated",
|
|
||||||
100
|
|
||||||
);
|
|
||||||
})
|
|
||||||
.expect([callback](std::string const& info) {
|
|
||||||
if (callback) callback(UpdateStatus::Failed, info, 0);
|
|
||||||
})
|
|
||||||
.progress([callback](auto&, double now, double total) {
|
|
||||||
if (callback)
|
|
||||||
callback(
|
|
||||||
UpdateStatus::Progress, "Downloading resources",
|
|
||||||
static_cast<uint8_t>(now / total * 100.0)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (checker.isError()) {
|
if (callback) callback(UpdateStatus::Finished, "Resources updated", 100);
|
||||||
if (callback) callback(UpdateStatus::Failed, checker.getError(), 0);
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.expect([callback](std::string const& info) {
|
.expect([callback](std::string const& info) {
|
||||||
if (callback) callback(UpdateStatus::Failed, info, 0);
|
if (callback) callback(UpdateStatus::Failed, info, 0);
|
||||||
|
})
|
||||||
|
.progress([callback](auto&, double now, double total) {
|
||||||
|
if (callback)
|
||||||
|
callback(
|
||||||
|
UpdateStatus::Progress, "Downloading resources",
|
||||||
|
static_cast<uint8_t>(now / total * 100.0)
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,14 +3,14 @@
|
||||||
|
|
||||||
USE_GEODE_NAMESPACE();
|
USE_GEODE_NAMESPACE();
|
||||||
|
|
||||||
std::unordered_set<BasicEventHandler*> Event::s_handlers = {};
|
std::unordered_set<EventListenerProtocol*> Event::s_listeners = {};
|
||||||
|
|
||||||
void BasicEventHandler::listen() {
|
void EventListenerProtocol::enable() {
|
||||||
Event::s_handlers.insert(this);
|
Event::s_listeners.insert(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BasicEventHandler::unlisten() {
|
void EventListenerProtocol::disable() {
|
||||||
Event::s_handlers.erase(this);
|
Event::s_listeners.erase(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicEventHandler::~BasicEventHandler() {
|
BasicEventHandler::~BasicEventHandler() {
|
||||||
|
@ -22,8 +22,8 @@ Event::~Event() {}
|
||||||
void Event::postFrom(Mod* m) {
|
void Event::postFrom(Mod* m) {
|
||||||
if (m) m_sender = m;
|
if (m) m_sender = m;
|
||||||
|
|
||||||
for (auto h : Event::s_handlers) {
|
for (auto h : Event::s_listeners) {
|
||||||
if (h->passThrough(this) == PassThrough::Stop) {
|
if (h->passThrough(this) == ListenerResult::Stop) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,3 @@ void Event::postFrom(Mod* m) {
|
||||||
Mod* Event::getSender() {
|
Mod* Event::getSender() {
|
||||||
return m_sender;
|
return m_sender;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_set<BasicEventHandler*> const& Event::getHandlers() {
|
|
||||||
return Event::s_handlers;
|
|
||||||
}
|
|
||||||
|
|
|
@ -37,6 +37,10 @@ void Loader::createDirectories() {
|
||||||
auto tempDir = this->getGeodeDirectory() / GEODE_TEMP_DIRECTORY;
|
auto tempDir = this->getGeodeDirectory() / GEODE_TEMP_DIRECTORY;
|
||||||
auto confDir = this->getGeodeDirectory() / GEODE_CONFIG_DIRECTORY;
|
auto confDir = this->getGeodeDirectory() / GEODE_CONFIG_DIRECTORY;
|
||||||
|
|
||||||
|
#ifdef GEODE_IS_MACOS
|
||||||
|
ghc::filesystem::create_directory(this->getSaveDirectory());
|
||||||
|
#endif
|
||||||
|
|
||||||
ghc::filesystem::create_directories(resDir);
|
ghc::filesystem::create_directories(resDir);
|
||||||
ghc::filesystem::create_directory(confDir);
|
ghc::filesystem::create_directory(confDir);
|
||||||
ghc::filesystem::create_directory(modDir);
|
ghc::filesystem::create_directory(modDir);
|
||||||
|
@ -465,7 +469,12 @@ ghc::filesystem::path Loader::getGameDirectory() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
ghc::filesystem::path Loader::getSaveDirectory() const {
|
ghc::filesystem::path Loader::getSaveDirectory() const {
|
||||||
|
// not using ~/Library/Caches
|
||||||
|
#ifdef GEODE_IS_MACOS
|
||||||
|
return ghc::filesystem::path("/Users/Shared/Geode");
|
||||||
|
#else
|
||||||
return ghc::filesystem::path(CCFileUtils::sharedFileUtils()->getWritablePath().c_str());
|
return ghc::filesystem::path(CCFileUtils::sharedFileUtils()->getWritablePath().c_str());
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
ghc::filesystem::path Loader::getGeodeDirectory() const {
|
ghc::filesystem::path Loader::getGeodeDirectory() const {
|
||||||
|
|
|
@ -507,45 +507,33 @@ float TextRenderer::adjustLineAlignment() {
|
||||||
auto anchor = node->getAnchorPoint().y;
|
auto anchor = node->getAnchorPoint().y;
|
||||||
switch (this->getCurrentVerticalAlign()) {
|
switch (this->getCurrentVerticalAlign()) {
|
||||||
case TextAlignment::Begin:
|
case TextAlignment::Begin:
|
||||||
default:
|
default: {
|
||||||
{
|
node->setPositionY(m_cursor.y - height * (1.f - anchor));
|
||||||
node->setPositionY(m_cursor.y - height * (1.f - anchor));
|
} break;
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TextAlignment::Center:
|
case TextAlignment::Center: {
|
||||||
{
|
node->setPositionY(m_cursor.y - maxHeight / 2 + height * (.5f - anchor));
|
||||||
node->setPositionY(m_cursor.y - maxHeight / 2 + height * (.5f - anchor));
|
} break;
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TextAlignment::End:
|
case TextAlignment::End: {
|
||||||
{
|
node->setPositionY(m_cursor.y - maxHeight + height * anchor);
|
||||||
node->setPositionY(m_cursor.y - maxHeight + height * anchor);
|
} break;
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
switch (this->getCurrentHorizontalAlign()) {
|
switch (this->getCurrentHorizontalAlign()) {
|
||||||
case TextAlignment::Begin:
|
case TextAlignment::Begin:
|
||||||
default:
|
default: {
|
||||||
{
|
// already correct
|
||||||
// already correct
|
} break;
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TextAlignment::Center:
|
case TextAlignment::Center: {
|
||||||
{
|
node->setPositionX(node->getPositionX() + (m_size.width - maxWidth) / 2);
|
||||||
node->setPositionX(node->getPositionX() + (m_size.width - maxWidth) / 2);
|
} break;
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TextAlignment::End:
|
case TextAlignment::End: {
|
||||||
{
|
node->setPositionX(
|
||||||
node->setPositionX(
|
node->getPositionX() + m_size.width - maxWidth - this->getCurrentIndent()
|
||||||
node->getPositionX() + m_size.width - maxWidth - this->getCurrentIndent()
|
);
|
||||||
);
|
} break;
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return maxHeight;
|
return maxHeight;
|
||||||
|
|
|
@ -126,37 +126,29 @@ Result<ccColor3B> geode::cocos::cc3bFromHexString(std::string const& hexValue) {
|
||||||
return Err("Invalid hex value");
|
return Err("Invalid hex value");
|
||||||
}
|
}
|
||||||
switch (hexValue.size()) {
|
switch (hexValue.size()) {
|
||||||
case 6:
|
case 6: {
|
||||||
{
|
auto r = static_cast<uint8_t>((numValue & 0xFF0000) >> 16);
|
||||||
auto r = static_cast<uint8_t>((numValue & 0xFF0000) >> 16);
|
auto g = static_cast<uint8_t>((numValue & 0x00FF00) >> 8);
|
||||||
auto g = static_cast<uint8_t>((numValue & 0x00FF00) >> 8);
|
auto b = static_cast<uint8_t>((numValue & 0x0000FF));
|
||||||
auto b = static_cast<uint8_t>((numValue & 0x0000FF));
|
return Ok(ccc3(r, g, b));
|
||||||
return Ok(ccc3(r, g, b));
|
} break;
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 3:
|
case 3: {
|
||||||
{
|
auto r = static_cast<uint8_t>(((numValue & 0xF00) >> 8) * 17);
|
||||||
auto r = static_cast<uint8_t>(((numValue & 0xF00) >> 8) * 17);
|
auto g = static_cast<uint8_t>(((numValue & 0x0F0) >> 4) * 17);
|
||||||
auto g = static_cast<uint8_t>(((numValue & 0x0F0) >> 4) * 17);
|
auto b = static_cast<uint8_t>(((numValue & 0x00F)) * 17);
|
||||||
auto b = static_cast<uint8_t>(((numValue & 0x00F)) * 17);
|
return Ok(ccc3(r, g, b));
|
||||||
return Ok(ccc3(r, g, b));
|
} break;
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
case 2: {
|
||||||
{
|
auto num = static_cast<uint8_t>(numValue);
|
||||||
auto num = static_cast<uint8_t>(numValue);
|
return Ok(ccc3(num, num, num));
|
||||||
return Ok(ccc3(num, num, num));
|
} break;
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1:
|
case 1: {
|
||||||
{
|
auto num = static_cast<uint8_t>(numValue) * 17;
|
||||||
auto num = static_cast<uint8_t>(numValue) * 17;
|
return Ok(ccc3(num, num, num));
|
||||||
return Ok(ccc3(num, num, num));
|
} break;
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: return Err("Invalid hex size, expected 1, 2, 3, or 6");
|
default: return Err("Invalid hex size, expected 1, 2, 3, or 6");
|
||||||
}
|
}
|
||||||
|
@ -177,57 +169,45 @@ Result<ccColor4B> geode::cocos::cc4bFromHexString(std::string const& hexValue) {
|
||||||
return Err("Invalid hex value");
|
return Err("Invalid hex value");
|
||||||
}
|
}
|
||||||
switch (hexValue.size()) {
|
switch (hexValue.size()) {
|
||||||
case 8:
|
case 8: {
|
||||||
{
|
auto r = static_cast<uint8_t>((numValue & 0xFF000000) >> 24);
|
||||||
auto r = static_cast<uint8_t>((numValue & 0xFF000000) >> 24);
|
auto g = static_cast<uint8_t>((numValue & 0x00FF0000) >> 16);
|
||||||
auto g = static_cast<uint8_t>((numValue & 0x00FF0000) >> 16);
|
auto b = static_cast<uint8_t>((numValue & 0x0000FF00) >> 8);
|
||||||
auto b = static_cast<uint8_t>((numValue & 0x0000FF00) >> 8);
|
auto a = static_cast<uint8_t>((numValue & 0x000000FF));
|
||||||
auto a = static_cast<uint8_t>((numValue & 0x000000FF));
|
return Ok(ccc4(r, g, b, a));
|
||||||
return Ok(ccc4(r, g, b, a));
|
} break;
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 6:
|
case 6: {
|
||||||
{
|
auto r = static_cast<uint8_t>((numValue & 0xFF0000) >> 16);
|
||||||
auto r = static_cast<uint8_t>((numValue & 0xFF0000) >> 16);
|
auto g = static_cast<uint8_t>((numValue & 0x00FF00) >> 8);
|
||||||
auto g = static_cast<uint8_t>((numValue & 0x00FF00) >> 8);
|
auto b = static_cast<uint8_t>((numValue & 0x0000FF));
|
||||||
auto b = static_cast<uint8_t>((numValue & 0x0000FF));
|
return Ok(ccc4(r, g, b, 255));
|
||||||
return Ok(ccc4(r, g, b, 255));
|
} break;
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 4:
|
case 4: {
|
||||||
{
|
auto r = static_cast<uint8_t>(((numValue & 0xF000) >> 12) * 17);
|
||||||
auto r = static_cast<uint8_t>(((numValue & 0xF000) >> 12) * 17);
|
auto g = static_cast<uint8_t>(((numValue & 0x0F00) >> 8) * 17);
|
||||||
auto g = static_cast<uint8_t>(((numValue & 0x0F00) >> 8) * 17);
|
auto b = static_cast<uint8_t>(((numValue & 0x00F0) >> 4) * 17);
|
||||||
auto b = static_cast<uint8_t>(((numValue & 0x00F0) >> 4) * 17);
|
auto a = static_cast<uint8_t>(((numValue & 0x000F)) * 17);
|
||||||
auto a = static_cast<uint8_t>(((numValue & 0x000F)) * 17);
|
return Ok(ccc4(r, g, b, a));
|
||||||
return Ok(ccc4(r, g, b, a));
|
} break;
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 3:
|
case 3: {
|
||||||
{
|
auto r = static_cast<uint8_t>(((numValue & 0xF00) >> 8) * 17);
|
||||||
auto r = static_cast<uint8_t>(((numValue & 0xF00) >> 8) * 17);
|
auto g = static_cast<uint8_t>(((numValue & 0x0F0) >> 4) * 17);
|
||||||
auto g = static_cast<uint8_t>(((numValue & 0x0F0) >> 4) * 17);
|
auto b = static_cast<uint8_t>(((numValue & 0x00F)) * 17);
|
||||||
auto b = static_cast<uint8_t>(((numValue & 0x00F)) * 17);
|
return Ok(ccc4(r, g, b, 255));
|
||||||
return Ok(ccc4(r, g, b, 255));
|
} break;
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
case 2: {
|
||||||
{
|
auto num = static_cast<uint8_t>(numValue);
|
||||||
auto num = static_cast<uint8_t>(numValue);
|
return Ok(ccc4(num, num, num, 255));
|
||||||
return Ok(ccc4(num, num, num, 255));
|
} break;
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1:
|
case 1: {
|
||||||
{
|
auto num = static_cast<uint8_t>(numValue) * 17;
|
||||||
auto num = static_cast<uint8_t>(numValue) * 17;
|
return Ok(ccc4(num, num, num, 255));
|
||||||
return Ok(ccc4(num, num, num, 255));
|
} break;
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: return Err("Invalid hex size, expected 1, 2, 3, 4, 6, or 8");
|
default: return Err("Invalid hex size, expected 1, 2, 3, 4, 6, or 8");
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,7 +127,7 @@ static std::unordered_map<std::string, SentAsyncWebRequestHandle> RUNNING_REQUES
|
||||||
static std::mutex RUNNING_REQUESTS_MUTEX;
|
static std::mutex RUNNING_REQUESTS_MUTEX;
|
||||||
|
|
||||||
SentAsyncWebRequest::SentAsyncWebRequest(AsyncWebRequest const& req, std::string const& id) :
|
SentAsyncWebRequest::SentAsyncWebRequest(AsyncWebRequest const& req, std::string const& id) :
|
||||||
m_id(id), m_url(req.m_url), m_target(req.m_target) {
|
m_id(id), m_url(req.m_url), m_target(req.m_target), m_httpHeaders(req.m_httpHeaders) {
|
||||||
#define AWAIT_RESUME() \
|
#define AWAIT_RESUME() \
|
||||||
while (m_paused) {} \
|
while (m_paused) {} \
|
||||||
if (m_cancelled) { \
|
if (m_cancelled) { \
|
||||||
|
@ -178,6 +178,12 @@ SentAsyncWebRequest::SentAsyncWebRequest(AsyncWebRequest const& req, std::string
|
||||||
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
|
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
|
||||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
|
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
|
||||||
|
|
||||||
|
curl_slist* headers = nullptr;
|
||||||
|
for (auto& header : m_httpHeaders) {
|
||||||
|
headers = curl_slist_append(headers, header.c_str());
|
||||||
|
}
|
||||||
|
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
|
||||||
|
|
||||||
struct ProgressData {
|
struct ProgressData {
|
||||||
SentAsyncWebRequest* self;
|
SentAsyncWebRequest* self;
|
||||||
std::ofstream* file;
|
std::ofstream* file;
|
||||||
|
@ -293,6 +299,11 @@ AsyncWebRequest& AsyncWebRequest::join(std::string const& requestID) {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AsyncWebRequest& AsyncWebRequest::header(std::string const& header) {
|
||||||
|
m_httpHeaders.push_back(header);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
AsyncWebResponse AsyncWebRequest::fetch(std::string const& url) {
|
AsyncWebResponse AsyncWebRequest::fetch(std::string const& url) {
|
||||||
m_url = url;
|
m_url = url;
|
||||||
return AsyncWebResponse(*this);
|
return AsyncWebResponse(*this);
|
||||||
|
|
|
@ -15,16 +15,15 @@ USE_GEODE_NAMESPACE();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
VersionInfo::VersionInfo(char const* versionString) {
|
VersionInfo::VersionInfo(char const* versionString) {
|
||||||
if (!THE_SSCANF(versionString, "v%d.%d.%d", &this->m_major, &this->m_minor, &this->m_patch))
|
if (!THE_SSCANF(versionString, "v%d.%d.%d", &this->m_major, &this->m_minor, &this->m_patch)) {
|
||||||
if (!THE_SSCANF(versionString, "%d.%d.%d", &this->m_major, &this->m_minor, &this->m_patch))
|
THE_SSCANF(versionString, "%d.%d.%d", &this->m_major, &this->m_minor, &this->m_patch);
|
||||||
THE_SSCANF(versionString, "%d %d %d", &this->m_major, &this->m_minor, &this->m_patch);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VersionInfo::validate(std::string const& string) {
|
bool VersionInfo::validate(std::string const& string) {
|
||||||
int buf0, buf1, buf2;
|
int buf0, buf1, buf2;
|
||||||
if (THE_SSCANF(string.c_str(), "v%d.%d.%d", &buf0, &buf1, &buf2)) return true;
|
if (THE_SSCANF(string.c_str(), "v%d.%d.%d", &buf0, &buf1, &buf2)) return true;
|
||||||
if (THE_SSCANF(string.c_str(), "%d.%d.%d", &buf0, &buf1, &buf2)) return true;
|
if (THE_SSCANF(string.c_str(), "%d.%d.%d", &buf0, &buf1, &buf2)) return true;
|
||||||
if (THE_SSCANF(string.c_str(), "%d %d %d", &buf0, &buf1, &buf2)) return true;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,31 +3,26 @@
|
||||||
USE_GEODE_NAMESPACE();
|
USE_GEODE_NAMESPACE();
|
||||||
|
|
||||||
#include <Geode/modify/MenuLayer.hpp>
|
#include <Geode/modify/MenuLayer.hpp>
|
||||||
class $modify(MenuLayer) {
|
|
||||||
void onMoreGames(CCObject*) {
|
struct MyMenuLayer : Modify<MyMenuLayer, MenuLayer> {
|
||||||
if (Mod::get()->getSettingValue<bool>("its-raining-after-all")) {
|
void onMoreGames(CCObject*) {
|
||||||
FLAlertLayer::create(
|
if (Mod::get()->getSettingValue<bool>("its-raining-after-all")) {
|
||||||
"Damn",
|
FLAlertLayer::create("Damn", ":(", "OK")->show();
|
||||||
":(",
|
}
|
||||||
"OK"
|
else {
|
||||||
)->show();
|
FLAlertLayer::create("Yay", "The weather report said it wouldn't rain today :)", "OK")
|
||||||
} else {
|
->show();
|
||||||
FLAlertLayer::create(
|
}
|
||||||
"Yay",
|
}
|
||||||
"The weather report said it wouldn't rain today :)",
|
|
||||||
"OK"
|
|
||||||
)->show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
GEODE_API bool GEODE_CALL geode_load(Mod*) {
|
GEODE_API bool GEODE_CALL geode_load(Mod*) {
|
||||||
// Dispatcher::get()->addFunction<void(GJGarageLayer*)>("test-garage-open", [](GJGarageLayer* gl) {
|
// Dispatcher::get()->addFunction<void(GJGarageLayer*)>("test-garage-open", [](GJGarageLayer*
|
||||||
// auto label = CCLabelBMFont::create("Dispatcher works!", "bigFont.fnt");
|
// gl) { auto label = CCLabelBMFont::create("Dispatcher works!", "bigFont.fnt");
|
||||||
// label->setPosition(100, 80);
|
// label->setPosition(100, 80);
|
||||||
// label->setScale(.4f);
|
// label->setScale(.4f);
|
||||||
// label->setZOrder(99999);
|
// label->setZOrder(99999);
|
||||||
// gl->addChild(label);
|
// gl->addChild(label);
|
||||||
// });
|
// });
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"geode": "v0.4.1",
|
"geode": "0.4.1",
|
||||||
"version": "v1.0.0",
|
"version": "1.0.0",
|
||||||
"id": "geode.testdep",
|
"id": "geode.testdep",
|
||||||
"name": "Geode Test Dependency",
|
"name": "Geode Test Dependency",
|
||||||
"developer": "Geode Team",
|
"developer": "Geode Team",
|
||||||
|
|
|
@ -2,90 +2,91 @@
|
||||||
|
|
||||||
USE_GEODE_NAMESPACE();
|
USE_GEODE_NAMESPACE();
|
||||||
|
|
||||||
auto test = [](){
|
auto test = []() {
|
||||||
log::info("Static logged");
|
log::info("Static logged");
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Exported functions
|
// Exported functions
|
||||||
GEODE_API bool GEODE_CALL geode_enable() {
|
GEODE_API bool GEODE_CALL geode_enable() {
|
||||||
log::info("Enabled");
|
log::info("Enabled");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
GEODE_API bool GEODE_CALL geode_disable() {
|
GEODE_API bool GEODE_CALL geode_disable() {
|
||||||
log::info("Disabled");
|
log::info("Disabled");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
GEODE_API bool GEODE_CALL geode_load(Mod*) {
|
GEODE_API bool GEODE_CALL geode_load(Mod*) {
|
||||||
log::info("Loaded");
|
log::info("Loaded");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
GEODE_API bool GEODE_CALL geode_unload() {
|
GEODE_API bool GEODE_CALL geode_unload() {
|
||||||
log::info("Unloaded");
|
log::info("Unloaded");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Modify
|
// Modify
|
||||||
#include <Geode/modify/GJGarageLayer.hpp>
|
#include <Geode/modify/GJGarageLayer.hpp>
|
||||||
class $modify(GJGarageLayerTest, GJGarageLayer) {
|
|
||||||
GJGarageLayerTest() :
|
|
||||||
myValue(1907) {}
|
|
||||||
|
|
||||||
int myValue;
|
struct GJGarageLayerTest : Modify<GJGarageLayerTest, GJGarageLayer> {
|
||||||
std::string myString = "yeah have fun finding a better thing for this";
|
GJGarageLayerTest() : myValue(1907) {}
|
||||||
bool init() {
|
|
||||||
if (!GJGarageLayer::init()) return false;
|
|
||||||
|
|
||||||
auto label = CCLabelBMFont::create("Modify works!", "bigFont.fnt");
|
int myValue;
|
||||||
label->setPosition(100, 110);
|
std::string myString = "yeah have fun finding a better thing for this";
|
||||||
label->setScale(.4f);
|
|
||||||
label->setZOrder(99999);
|
|
||||||
addChild(label);
|
|
||||||
|
|
||||||
if (m_fields->myValue == 1907 && m_fields->myString != "") {
|
bool init() {
|
||||||
auto label = CCLabelBMFont::create("Field default works!", "bigFont.fnt");
|
if (!GJGarageLayer::init()) return false;
|
||||||
label->setPosition(100, 100);
|
|
||||||
label->setScale(.4f);
|
|
||||||
label->setZOrder(99999);
|
|
||||||
addChild(label);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Data Store
|
auto label = CCLabelBMFont::create("Modify works!", "bigFont.fnt");
|
||||||
auto ds = Mod::get()->getDataStore();
|
label->setPosition(100, 110);
|
||||||
int out = ds["times-opened"];
|
label->setScale(.4f);
|
||||||
ds["times-opened"] = out + 1;
|
label->setZOrder(99999);
|
||||||
|
addChild(label);
|
||||||
|
|
||||||
std::string text = std::string("Times opened: ") + std::to_string(out);
|
if (m_fields->myValue == 1907 && m_fields->myString != "") {
|
||||||
|
auto label = CCLabelBMFont::create("Field default works!", "bigFont.fnt");
|
||||||
|
label->setPosition(100, 100);
|
||||||
|
label->setScale(.4f);
|
||||||
|
label->setZOrder(99999);
|
||||||
|
addChild(label);
|
||||||
|
}
|
||||||
|
|
||||||
auto label2 = CCLabelBMFont::create(text.c_str(), "bigFont.fnt");
|
// Data Store
|
||||||
label2->setPosition(100, 90);
|
auto ds = Mod::get()->getDataStore();
|
||||||
label2->setScale(.4f);
|
int out = ds["times-opened"];
|
||||||
label2->setZOrder(99999);
|
ds["times-opened"] = out + 1;
|
||||||
addChild(label2);
|
|
||||||
|
|
||||||
// Dispatch system pt. 1
|
std::string text = std::string("Times opened: ") + std::to_string(out);
|
||||||
// auto fn = Dispatcher::get()->getFunction<void(GJGarageLayer*)>("test-garage-open");
|
|
||||||
// fn(this);
|
|
||||||
|
|
||||||
return true;
|
auto label2 = CCLabelBMFont::create(text.c_str(), "bigFont.fnt");
|
||||||
}
|
label2->setPosition(100, 90);
|
||||||
|
label2->setScale(.4f);
|
||||||
|
label2->setZOrder(99999);
|
||||||
|
addChild(label2);
|
||||||
|
|
||||||
|
// Dispatch system pt. 1
|
||||||
|
// auto fn = Dispatcher::get()->getFunction<void(GJGarageLayer*)>("test-garage-open");
|
||||||
|
// fn(this);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*// Event system pt. 2
|
/*// Event system pt. 2
|
||||||
int a = (0, []() {
|
int a = (0, []() {
|
||||||
|
|
||||||
Dispatcher::get()->addSelector("test-garage-open", [](GJGarageLayer* gl) {
|
Dispatcher::get()->addSelector("test-garage-open", [](GJGarageLayer* gl) {
|
||||||
auto label = CCLabelBMFont::create("EventCenter works!", "bigFont.fnt");
|
auto label = CCLabelBMFont::create("EventCenter works!", "bigFont.fnt");
|
||||||
label->setPosition(100, 80);
|
label->setPosition(100, 80);
|
||||||
label->setScale(.4f);
|
label->setScale(.4f);
|
||||||
label->setZOrder(99999);
|
label->setZOrder(99999);
|
||||||
gl->addChild(label);
|
gl->addChild(label);
|
||||||
|
|
||||||
TestDependency::depTest(gl);
|
TestDependency::depTest(gl);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Event system pt. 2
|
// Event system pt. 2
|
||||||
// $observe("test-garage-open", GJGarageLayer*, evt) {
|
// $observe("test-garage-open", GJGarageLayer*, evt) {
|
||||||
|
@ -99,6 +100,5 @@ int a = (0, []() {
|
||||||
// // API pt. 2
|
// // API pt. 2
|
||||||
// TestDependency::depTest(gl);
|
// TestDependency::depTest(gl);
|
||||||
// }
|
// }
|
||||||
return 0;
|
return 0;
|
||||||
}());*/
|
}());*/
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"geode": "v0.4.1",
|
"geode": "0.4.1",
|
||||||
"version": "v1.0.0",
|
"version": "1.0.0",
|
||||||
"id": "geode.test",
|
"id": "geode.test",
|
||||||
"name": "Geode Test",
|
"name": "Geode Test",
|
||||||
"developer": "Geode Team",
|
"developer": "Geode Team",
|
||||||
|
@ -11,7 +11,7 @@
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
{
|
{
|
||||||
"id": "geode.testdep",
|
"id": "geode.testdep",
|
||||||
"version": "v1.0.*",
|
"version": "1.0.*",
|
||||||
"required": true
|
"required": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
Loading…
Reference in a new issue