mirror of
https://github.com/geode-sdk/geode.git
synced 2025-04-24 05:14:40 -04:00
Merge branch 'main' into layout
This commit is contained in:
commit
ee68a73629
18 changed files with 145 additions and 93 deletions
.github/workflows
CMakeLists.txtLICENSEREADME.mdVERSIONloader
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
|
@ -56,7 +56,7 @@ jobs:
|
|||
fileName: ${{ matrix.config.cli_name }}
|
||||
tarBall: false
|
||||
zipBall: false
|
||||
out-file-path: "cli"
|
||||
out-file-path: "cli"
|
||||
|
||||
- name: Unzip CLI
|
||||
run: |
|
||||
|
|
|
@ -94,11 +94,11 @@ if (PROJECT_IS_TOP_LEVEL)
|
|||
elseif(EXISTS ${GEODE_PLATFORM_BIN_PATH})
|
||||
target_link_libraries(${PROJECT_NAME} INTERFACE "${GEODE_PLATFORM_BIN_PATH}")
|
||||
target_precompile_headers(${PROJECT_NAME} INTERFACE
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/DefaultInclude.hpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/Loader.hpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/UI.hpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/cocos/cocos2dx/include/cocos2d.h"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/cocos/extensions/cocos-ext.h"
|
||||
"${GEODE_LOADER_PATH}/include/Geode/DefaultInclude.hpp"
|
||||
"${GEODE_LOADER_PATH}/include/Geode/Loader.hpp"
|
||||
"${GEODE_LOADER_PATH}/include/Geode/UI.hpp"
|
||||
"${GEODE_LOADER_PATH}/include/Geode/cocos/cocos2dx/include/cocos2d.h"
|
||||
"${GEODE_LOADER_PATH}/include/Geode/cocos/extensions/cocos-ext.h"
|
||||
)
|
||||
else()
|
||||
message(FATAL_ERROR "No valid loader binary to link to! Install a pre-built binary for version ${PROJECT_VERSION} with Geode CLI or build it from source.")
|
||||
|
|
23
LICENSE
Normal file
23
LICENSE
Normal file
|
@ -0,0 +1,23 @@
|
|||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
# Geode SDK
|
||||
|
||||
**Geode** is a [Geometry Dash](https://store.steampowered.com/app/322170/Geometry_Dash/) **mod loader** and **modding SDK** with a modern approach towards mod development. Unlike previous mod loaders, which merely inject the DLLs and let devs handle the rest, Geode aims to be a more comprehensive project, which manages loaded mods & hooks itself. Geode has been built to ensure performance, compatibility, portability and ease of use. For devs, Geode means **easy development and portability**; for end users, Geode means **an uniform and easy experience** using mods.
|
||||
**Geode** is a [Geometry Dash](https://store.steampowered.com/app/322170/Geometry_Dash/) **mod loader** and **modding SDK** with a modern approach towards mod development. Unlike previous mod loaders, which merely inject the DLLs and let devs handle the rest, Geode aims to be a more comprehensive project, which manages loaded mods & hooks itself. Geode has been built to ensure performance, compatibility, portability and ease of use. For devs, Geode means **easy development and portability**; for end users, **a uniform and easy experience** using mods.
|
||||
|
||||
## Why Geode?
|
||||
|
||||
|
@ -29,7 +29,7 @@ This code hooks the "More Games" button in Geometry Dash, and makes it show a di
|
|||
|
||||
One of our main design goals with Geode has been to make a framework so good that **after using it once, you never want to go back**.
|
||||
|
||||
> :warning: It is important to note that Geode is **not meant to make learning to mod easier**. To make a good GD mod, you will still need to learn the ins and outs of C++, reverse engineering, byte patching, and everything else. Geode is merely a collection of tools that make modding more enjoyable for people who are already familiar with it; not a magic wand for making mods without the hours of experience and practice required.
|
||||
> :warning: It is important to note that Geode is **not meant to make learning to mod easier**. To make a good GD mod, you will still need to learn the ins and outs of C++, reverse engineering, byte patching, and everything else. Geode is merely a collection of tools that make modding more enjoyable for people who are already familiar with it; not a magic wand for making mods without the hours of experience and practice required.
|
||||
|
||||
## Documentation
|
||||
|
||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
0.4.8
|
||||
0.5.0
|
|
@ -6,6 +6,7 @@
|
|||
#include "ui/EnterLayerEvent.hpp"
|
||||
#include "ui/IconButtonSprite.hpp"
|
||||
#include "ui/InputNode.hpp"
|
||||
#include "ui/LayerBG.hpp"
|
||||
#include "ui/ListView.hpp"
|
||||
#include "ui/MDPopup.hpp"
|
||||
#include "ui/MDTextArea.hpp"
|
||||
|
|
|
@ -16,9 +16,9 @@ namespace geode::base {
|
|||
#if defined(GEODE_IS_MACOS) || defined(GEODE_IS_ANDROID)
|
||||
namespace gd {
|
||||
struct _internal_string {
|
||||
uintptr_t m_len;
|
||||
uintptr_t m_capacity;
|
||||
int m_refcount;
|
||||
size_t m_len;
|
||||
size_t m_capacity;
|
||||
int m_refcount;
|
||||
};
|
||||
|
||||
class GEODE_DLL string {
|
||||
|
@ -26,18 +26,17 @@ namespace gd {
|
|||
string();
|
||||
string(char const* ok);
|
||||
string(std::string ok) : string(ok.c_str()) {}
|
||||
operator std::string() {
|
||||
return std::string((char*)m_data, m_data[-1].m_len);
|
||||
}
|
||||
operator std::string() const {
|
||||
return std::string((char*)m_data, m_data[-1].m_len);
|
||||
}
|
||||
bool operator==(string const& other) const;
|
||||
string(string const& ok);
|
||||
string& operator=(char const* ok);
|
||||
string& operator=(string const& ok);
|
||||
__attribute__((noinline)) ~string();
|
||||
char const* c_str() const {return (char const*)m_data; }
|
||||
protected:
|
||||
char const* c_str() const { return (char const*)m_data; }
|
||||
size_t size() const { return m_data[-1].m_len; }
|
||||
protected:
|
||||
_internal_string* m_data;
|
||||
};
|
||||
|
||||
|
@ -283,14 +282,8 @@ namespace gd {
|
|||
template <typename T>
|
||||
class GEODE_DLL vector {
|
||||
public:
|
||||
operator std::vector<T>() {
|
||||
std::vector<T> out;
|
||||
using value_type = T;
|
||||
|
||||
for (auto i = m_start; i != m_finish; ++i) {
|
||||
out.push_back(*i);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
operator std::vector<T>() const {
|
||||
std::vector<T> out;
|
||||
|
||||
|
@ -315,6 +308,11 @@ namespace gd {
|
|||
T& front() {
|
||||
return *m_start;
|
||||
}
|
||||
|
||||
auto begin() { return m_start; }
|
||||
auto end() { return m_finish; }
|
||||
auto begin() const { return static_cast<const T*>(m_start); }
|
||||
auto end() const { return static_cast<const T*>(m_finish); }
|
||||
|
||||
vector(vector const& lol) : vector(std::vector<T>(lol)) {}
|
||||
|
||||
|
@ -459,6 +457,8 @@ namespace gd {
|
|||
template <typename T>
|
||||
class GEODE_DLL vector {
|
||||
public:
|
||||
using value_type = T;
|
||||
|
||||
operator std::vector<T>() {
|
||||
return m_internal;
|
||||
}
|
||||
|
|
|
@ -64,6 +64,10 @@ public:
|
|||
* @js getInstance
|
||||
*/
|
||||
static CCFileUtils* sharedFileUtils();
|
||||
|
||||
GEODE_ADD(
|
||||
static CCFileUtils* get();
|
||||
);
|
||||
|
||||
/**
|
||||
* Destroys the instance of CCFileUtils.
|
||||
|
|
|
@ -63,6 +63,7 @@ namespace geode {
|
|||
std::ofstream m_logStream;
|
||||
std::vector<ghc::filesystem::path> m_modDirectories;
|
||||
std::vector<FailedModInfo> m_erroredMods;
|
||||
std::vector<ghc::filesystem::path> m_texturePaths;
|
||||
LoaderSettings m_loadedSettings;
|
||||
|
||||
bool m_isSetup = false;
|
||||
|
@ -87,9 +88,12 @@ namespace geode {
|
|||
|
||||
template <class, class, class>
|
||||
friend class modifier::FieldIntermediate;
|
||||
|
||||
void updateResourcePaths();
|
||||
void updateModResources(Mod* mod);
|
||||
|
||||
friend bool GEODE_CALL ::geode_implicit_load(Mod*);
|
||||
|
||||
|
||||
public:
|
||||
~Loader();
|
||||
|
||||
|
@ -175,17 +179,13 @@ namespace geode {
|
|||
);
|
||||
|
||||
void clearLogs();
|
||||
|
||||
|
||||
/**
|
||||
* You shouldn't be calling this manually,
|
||||
* but if you are, make sure to set
|
||||
* Mod::m_addResourcesToSearchPath to true
|
||||
* first
|
||||
* Do not call manually unless you know what you're doing.
|
||||
*/
|
||||
void updateModResourcePaths(Mod*);
|
||||
void updateResourcePaths();
|
||||
void updateModResources(Mod* mod);
|
||||
void updateResources();
|
||||
void addTexturePath(ghc::filesystem::path const& path);
|
||||
void removeTexturePath(ghc::filesystem::path const& path);
|
||||
|
||||
/**
|
||||
* Check if a mod with an ID is installed. Any
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <Geode/DefaultInclude.hpp>
|
||||
#include <cocos2d.h>
|
||||
|
||||
namespace geode {
|
||||
|
|
|
@ -120,7 +120,7 @@ namespace geode::utils::ranges {
|
|||
|
||||
template<class R, ValidConstContainer C, class Reducer>
|
||||
requires requires(Reducer r, R& acc, typename C::value_type t) {
|
||||
{ r(acc, t) } -> std::same_as<void>;
|
||||
r(acc, t);
|
||||
}
|
||||
R reduce(C const& container, Reducer reducer) {
|
||||
auto res = R();
|
||||
|
|
|
@ -23,3 +23,9 @@ CCDirector* CCDirector::get() {
|
|||
CCEGLView* CCEGLView::get() {
|
||||
return CCDirector::sharedDirector()->getOpenGLView();
|
||||
}
|
||||
|
||||
CCFileUtils* CCFileUtils::get() {
|
||||
return CCFileUtils::sharedFileUtils();
|
||||
}
|
||||
|
||||
#pragma warning(pop)
|
||||
|
|
|
@ -67,6 +67,23 @@ static void updateIndexProgress(
|
|||
}
|
||||
}
|
||||
|
||||
template<class T = CCNode>
|
||||
requires std::is_base_of_v<CCNode, T>
|
||||
T* setIDSafe(CCNode* node, int index, const char* id) {
|
||||
if constexpr (std::is_same_v<CCNode, T>) {
|
||||
if (auto child = getChild(node, index)) {
|
||||
child->setID(id);
|
||||
return child;
|
||||
}
|
||||
} else {
|
||||
if (auto child = getChildOfType<T>(node, index)) {
|
||||
child->setID(id);
|
||||
return child;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#include <Geode/modify/MenuLayer.hpp>
|
||||
class $modify(CustomMenuLayer, MenuLayer) {
|
||||
void destructor() {
|
||||
|
@ -82,8 +99,6 @@ class $modify(CustomMenuLayer, MenuLayer) {
|
|||
// hook order support yet so gotta do this to ensure)
|
||||
addIDsToMenuLayer(this);
|
||||
|
||||
Loader::get()->updateResourcePaths();
|
||||
|
||||
auto winSize = CCDirector::sharedDirector()->getWinSize();
|
||||
|
||||
// add geode button
|
||||
|
|
|
@ -1,21 +1,13 @@
|
|||
#include <Geode/loader/Loader.hpp>
|
||||
#include <Geode/modify/LoadingLayer.hpp>
|
||||
|
||||
USE_GEODE_NAMESPACE();
|
||||
|
||||
#include <Geode/modify/GameManager.hpp>
|
||||
class $modify(GameManager) {
|
||||
void reloadAllStep2() {
|
||||
GameManager::reloadAllStep2();
|
||||
Loader::get()->updateResourcePaths();
|
||||
}
|
||||
};
|
||||
|
||||
#include <Geode/modify/LoadingLayer.hpp>
|
||||
class $modify(LoadingLayer) {
|
||||
void loadAssets() {
|
||||
LoadingLayer::loadAssets();
|
||||
if (this->m_loadStep == 5) {
|
||||
Loader::get()->updateResourcePaths();
|
||||
// this is in case the user refreshes texture quality at runtime
|
||||
if (this->m_loadStep == 10) {
|
||||
Loader::get()->updateResources();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,6 +40,9 @@ InternalMod::InternalMod() : Mod(getInternalModInfo()) {
|
|||
m_saveDirPath = Loader::get()->getGeodeSaveDirectory() / GEODE_MOD_DIRECTORY / m_info.m_id;
|
||||
ghc::filesystem::create_directories(m_saveDirPath);
|
||||
|
||||
// make sure spritesheets get added
|
||||
m_addResourcesToSearchPath = true;
|
||||
|
||||
auto sett = this->loadSettings();
|
||||
if (!sett) {
|
||||
log::log(Severity::Error, this, "{}", sett.error());
|
||||
|
|
|
@ -50,63 +50,67 @@ void Loader::createDirectories() {
|
|||
}
|
||||
|
||||
void Loader::updateResourcePaths() {
|
||||
log::debug("Updating resources paths");
|
||||
log::debug("Setting resource paths");
|
||||
|
||||
// add own geode/resources directory
|
||||
CCFileUtils::sharedFileUtils()->addSearchPath(
|
||||
(this->getGeodeDirectory() / GEODE_RESOURCE_DIRECTORY).string().c_str()
|
||||
);
|
||||
// reset search paths
|
||||
CCFileUtils::get()->setSearchPaths({
|
||||
"Resources",
|
||||
(this->getGeodeDirectory() / GEODE_RESOURCE_DIRECTORY).string(),
|
||||
(this->getGeodeDirectory() / GEODE_TEMP_DIRECTORY).string()
|
||||
});
|
||||
|
||||
// add geode/temp for accessing root resources in mods
|
||||
auto tempDir = this->getGeodeDirectory() / GEODE_TEMP_DIRECTORY;
|
||||
CCFileUtils::sharedFileUtils()->addSearchPath(tempDir.string().c_str());
|
||||
|
||||
// add geode/temp/mod.id/resources for accessing additional resources in mods
|
||||
for (auto& [_, mod] : m_mods) {
|
||||
this->updateModResourcePaths(mod);
|
||||
// add mods' search paths
|
||||
for (auto const& [_, mod] : m_mods) {
|
||||
auto searchPath = this->getGeodeDirectory() /
|
||||
GEODE_TEMP_DIRECTORY / mod->getID() / "resources";
|
||||
|
||||
// add search path
|
||||
CCFileUtils::get()->addSearchPath(searchPath.string().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void Loader::updateModResourcePaths(Mod* mod) {
|
||||
if (mod->m_addResourcesToSearchPath) {
|
||||
CCFileUtils::sharedFileUtils()->addSearchPath(
|
||||
(this->getGeodeDirectory() /
|
||||
GEODE_TEMP_DIRECTORY /
|
||||
mod->getID() /
|
||||
"resources"
|
||||
).string().c_str()
|
||||
);
|
||||
log::debug("Added resources path for {}", mod->getID());
|
||||
// add custom texture paths
|
||||
for (auto const& path : m_texturePaths) {
|
||||
CCFileUtils::get()->addSearchPath(path.string().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void Loader::updateModResources(Mod* mod) {
|
||||
if (!mod->m_addResourcesToSearchPath) {
|
||||
log::debug("Mod {} doesn't have resources, skipping", mod->getID());
|
||||
return;
|
||||
}
|
||||
|
||||
auto searchPath = this->getGeodeDirectory() /
|
||||
GEODE_TEMP_DIRECTORY / mod->getID() / "resources";
|
||||
|
||||
log::debug("Adding resources for {}", mod->getID());
|
||||
|
||||
// add spritesheets
|
||||
for (auto const& sheet : mod->m_info.m_spritesheets) {
|
||||
auto png = sheet + ".png";
|
||||
auto plist = sheet + ".plist";
|
||||
auto ccfu = CCFileUtils::sharedFileUtils();
|
||||
|
||||
if (
|
||||
png == std::string(
|
||||
ccfu->fullPathForFilename(png.c_str(), false)
|
||||
) ||
|
||||
plist == std::string(
|
||||
ccfu->fullPathForFilename(plist.c_str(), false)
|
||||
)
|
||||
png == std::string(ccfu->fullPathForFilename(png.c_str(), false)) ||
|
||||
plist == std::string(ccfu->fullPathForFilename(plist.c_str(), false))
|
||||
) {
|
||||
log::warn("The resource dir of \"{}\" is missing \"{}\" png and/or plist files", mod->m_info.m_id, sheet);
|
||||
log::warn(
|
||||
"The resource dir of \"{}\" is missing \"{}\" png and/or plist files",
|
||||
mod->m_info.m_id, sheet
|
||||
);
|
||||
} else {
|
||||
CCTextureCache::sharedTextureCache()->addImage(png.c_str(), false);
|
||||
CCSpriteFrameCache::sharedSpriteFrameCache()
|
||||
->addSpriteFramesWithFile(plist.c_str());
|
||||
|
||||
log::debug("Added resources for {}", mod->getID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Loader::updateResources() {
|
||||
log::debug("Adding mod resources");
|
||||
log::debug("Adding resources");
|
||||
|
||||
this->updateResourcePaths();
|
||||
|
||||
// add own spritesheets
|
||||
this->updateModResources(InternalMod::get());
|
||||
|
@ -117,6 +121,14 @@ void Loader::updateResources() {
|
|||
}
|
||||
}
|
||||
|
||||
void Loader::addTexturePath(ghc::filesystem::path const& path) {
|
||||
m_texturePaths.push_back(path);
|
||||
}
|
||||
|
||||
void Loader::removeTexturePath(ghc::filesystem::path const& path) {
|
||||
ranges::remove(m_texturePaths, path);
|
||||
}
|
||||
|
||||
size_t Loader::loadModsFromDirectory(
|
||||
ghc::filesystem::path const& dir, bool recursive
|
||||
) {
|
||||
|
@ -353,12 +365,6 @@ bool Loader::setup() {
|
|||
this->loadSettings();
|
||||
this->refreshMods();
|
||||
|
||||
// add resources on startup
|
||||
this->queueInGDThread([]() {
|
||||
Loader::get()->updateResourcePaths();
|
||||
Loader::get()->updateResources();
|
||||
});
|
||||
|
||||
m_isSetup = true;
|
||||
|
||||
return true;
|
||||
|
@ -447,12 +453,8 @@ size_t Loader::getFieldIndexForClass(size_t hash) {
|
|||
}
|
||||
|
||||
VersionInfo Loader::minModVersion() {
|
||||
// patches are always backwards-compatible. if not, we have failed
|
||||
return VersionInfo {
|
||||
Loader::getVersion().getMajor(),
|
||||
Loader::getVersion().getMinor(),
|
||||
0,
|
||||
};
|
||||
// Remember to update when deleting features!
|
||||
return VersionInfo { 0, 4, 0 };
|
||||
}
|
||||
|
||||
VersionInfo Loader::maxModVersion() {
|
||||
|
|
|
@ -51,7 +51,7 @@ Result<Mod*> Loader::loadModFromFile(std::string const& path) {
|
|||
|
||||
// add mod resources
|
||||
this->queueInGDThread([this, mod]() {
|
||||
this->updateModResourcePaths(mod);
|
||||
this->updateResourcePaths();
|
||||
this->updateModResources(mod);
|
||||
});
|
||||
|
||||
|
|
|
@ -35,6 +35,11 @@ namespace gd {
|
|||
reinterpret_cast<void(*)(_internal_string*, void*)>(geode::base::get() + 0x489f78)(&m_data[-1], al);
|
||||
}
|
||||
}
|
||||
bool string::operator==(string const& other) const {
|
||||
if (size() != other.size()) return false;
|
||||
return strcmp(c_str(), other.c_str()) == 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue