Merge branch 'main' into new-index-but-better

This commit is contained in:
HJfod 2024-04-13 21:47:56 +03:00
commit 33af7befed
35 changed files with 363 additions and 45 deletions

2
.gitignore vendored
View file

@ -55,6 +55,8 @@ docs
loader/src/internal/about.cpp
loader/src/internal/resources.hpp
loader/resources/mod.json
loader/test/dependency/mod.json
loader/test/main/mod.json
loader/resources/version
loader/resources/blanks/rename.js
loader/resources/about.md

View file

@ -18,6 +18,8 @@ option(GEODE_USE_BREAKPAD "Enables the use of the Breakpad library for crash dum
# Read version
file(READ VERSION GEODE_VERSION)
string(STRIP "${GEODE_VERSION}" GEODE_VERSION)
set(GEODE_VERSION "${GEODE_VERSION}" CACHE INTERNAL "Geode version")
set(GEODE_VERSION_FULL "${GEODE_VERSION}" CACHE INTERNAL "Geode version full")
# Check if version has a tag like v1.0.0-alpha
string(FIND ${GEODE_VERSION} "-" GEODE_VERSION_HAS_TAG)
@ -199,8 +201,16 @@ if (WIN32)
endif()
endif()
# We do not support anything below SDK 23
if (ANDROID)
string(REGEX MATCH "[0-9]+" ANDROID_PLATFORM_NUMBER "${ANDROID_PLATFORM}")
if (ANDROID_PLATFORM_NUMBER LESS 23)
message(FATAL_ERROR "Specified target Android SDK version is too low (${ANDROID_PLATFORM_NUMBER}), must be 23 or higher")
endif()
endif()
set(MAT_JSON_AS_INTERFACE ON)
CPMAddPackage("gh:geode-sdk/json#96a9500")
CPMAddPackage("gh:geode-sdk/json#28f157b")
CPMAddPackage("gh:fmtlib/fmt#10.1.1")
CPMAddPackage("gh:gulrak/filesystem#3e5b930")
@ -231,7 +241,7 @@ if (DEFINED GEODE_TULIPHOOK_REPO_PATH)
message(STATUS "Using ${GEODE_TULIPHOOK_REPO_PATH} for TulipHook")
add_subdirectory(${GEODE_TULIPHOOK_REPO_PATH} ${GEODE_TULIPHOOK_REPO_PATH}/build)
else()
CPMAddPackage("gh:geode-sdk/TulipHook#7fa328b")
CPMAddPackage("gh:geode-sdk/TulipHook#3ec2e6e")
endif()
set(CMAKE_WARN_DEPRECATED ON CACHE BOOL "" FORCE)

View file

@ -1 +1 @@
2.0.0-beta.23
2.0.0-beta.24

View file

@ -86,9 +86,18 @@ function(setup_geode_mod proname)
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/mod.json" MOD_JSON)
string(JSON MOD_ID GET "${MOD_JSON}" "id")
string(JSON MOD_VERSION GET "${MOD_JSON}" "version")
string(JSON TARGET_GEODE_VERSION GET "${MOD_JSON}" "geode")
string(JSON MOD_HAS_API ERROR_VARIABLE MOD_DOESNT_HAVE_API GET "${MOD_JSON}" "api")
string(JSON MOD_HAS_DEPS ERROR_VARIABLE MOD_DOESNT_HAVE_DEPS GET "${MOD_JSON}" "dependencies")
if ("${TARGET_GEODE_VERSION}" STREQUAL "${GEODE_VERSION_FULL}")
message(STATUS "Mod ${MOD_ID} is compiling for Geode version ${GEODE_VERSION_FULL}")
else()
message(FATAL_ERROR
"Mod ${MOD_ID} is made for Geode version ${TARGET_GEODE_VERSION} but you have ${GEODE_VERSION_FULL} SDK installed. Please change the Geode version in your mod.json. "
)
endif()
# Add this mod to the list of known externals mods
list(APPEND GEODE_MODS_BEING_BUILT "${MOD_ID}:${MOD_VERSION}")
# Ensure that the list of mods being built is global (persists between setup_geode_mod calls)

View file

@ -17,3 +17,38 @@ namespace {
// to make sure the instance is set into the sharedMod<> in load time
static auto mod = geode::getMod();
}
#if defined(_DEBUG) && defined(GEODE_IS_WINDOWS)
// This bypasses any of the heap validation measures that are injected when compiling in Debug.
// Without these, the game will very likely crash when the mod tries to free memory allocated by the game (or another non-debug mod).
static inline void* relallocthrow(size_t size) {
void* p;
while ((p = HeapAlloc(GetProcessHeap(), 0, size)) == 0) {
if (_callnewh(size) == 0) {
static const std::bad_alloc exc;
throw exc;
}
}
return p;
}
static inline void relfree(void* block) {
HeapFree(GetProcessHeap(), 0, block);
}
void* operator new(size_t size) {
return relallocthrow(size);
}
void* operator new[](size_t size) {
return relallocthrow(size);
}
void operator delete(void* block) noexcept {
relfree(block);
}
#endif

View file

@ -0,0 +1,16 @@
!insertmacro LANGFILE_EXT French
!pragma warning disable 6030
${LangFileString} MUI_TEXT_WELCOME_INFO_TEXT "Le programme d'installation vous guidera tout au long de l'installation de $(^NameDA).$\r$\n$\r$\nAvant de démarrer l'installation, assurez-vous que Geometry Dash n'est pas en cours d'exécution.$\r$\n$\r$\n$_CLICK"
${LangFileString} MUI_UNTEXT_WELCOME_INFO_TEXT "Le programme d'installation vous guidera tout au long de la désinstallation de $(^NameDA).$\r$\n$\r$\nAvant de démarrer la désinstallation, assurez-vous que Geometry Dash n'est pas en cours d'exécution.$\r$\n$\r$\n$_CLICK"
!pragma warning default 6030
; installer
${LangFileString} GEODE_TEXT_GD_MISSING "$\r$\n$\r$\nGeometry Dash n'est pas installé sur ce chemin !"
${LangFileString} GEODE_TEXT_MH_ALREADY_INSTALLED "Ce chemin a déjà Mega Hack v6/v7 installé !$\r$\nGeode ne fonctionne pas avec MHv6/v7 (MHv8 sera compatible avec Geode).$\r$\nVeuillez le désinstaller avant de continuer."
${LangFileString} GEODE_TEXT_MOD_LOADER_ALREADY_INSTALLED "Ce chemin contient déjà un autre chargeur de mod installé !$\r$\nGeode ne fonctionne avec aucun autre chargeur de mod.$\r$\nVeuillez le désinstaller avant de continuer. (the dll trademark)"
; uninstaller
${LangFileString} GEODE_UNTEXT_GEODE_MISSING "Geode n'est pas installé sur ce chemin !"

View file

@ -0,0 +1,15 @@
${LangFileString} MUI_TEXT_WELCOME_INFO_TEXT "Το setup θα σας καθοδηγήσει για την εγκατάσταση του $(^NameDA).$\r$\n$\r$\nΠρίν ξεκινήσετε την εγκατάσταση, βεβαιωθήτε ότι το Geometry Dash δεν τρέχει.$\r$\n$\r$\n$_CLICK"
${LangFileString} MUI_UNTEXT_WELCOME_INFO_TEXT "Το setup θα σας καθοδηγήσει για την απεγκατάσταση του $(^NameDA).$\r$\n$\r$\nΠριν την απεγκατάσταση, βεβαιωθήτε ότι το Geometry Dash δεν τρέχει.$\r$\n$\r$\n$_CLICK"
!pragma warning default 6030
; installer
${LangFileString} GEODE_TEXT_GD_MISSING "$\r$\n$\r$\nΑυτό το path δεν έχει το Geometry Dash εγκατεστημένο!"
${LangFileString} GEODE_TEXT_MH_ALREADY_INSTALLED "Αυτό το path έχει ήδη το Mega Hack v6/v7 εγκατεστημένο!$\r$\nΤο Geode δεν λειτουργεί με το MHv6/v7 (MHv8 θα είναι συμβατό με το Geode).$\r$\nΠαρακαλώ, απεγκαταστήστε το πριν προχωρήσετε."
${LangFileString} GEODE_TEXT_MOD_LOADER_ALREADY_INSTALLED "Αυτό το path έχει ήδη ένα mod loader εγκατεστημένο!$\r$\nΤο Geode δεν λειτουργεί με οποιοδήποτε άλλο mod loader.$\r$\nΠαρακαλώ, απεγκαταστήστε το πριν προχωρήσετε. (the dll trademark)"
; uninstaller
${LangFileString} GEODE_UNTEXT_GEODE_MISSING "Αυτό το path δεν έχει το Geode εγκατεστημένο!"

View file

@ -2,8 +2,8 @@
!pragma warning disable 6030
${LangFileString} MUI_TEXT_WELCOME_INFO_TEXT "セットアップは$(^NameDA)のインストールを案内します。$\r$\n$\r$\nインストールを開始する前に、Geometry Dashが実行されていないことを確認してください。$\r$\n$\r$\n$_CLICK"
${LangFileString} MUI_UNTEXT_WELCOME_INFO_TEXT "セットアップは$(^NameDA)のアンインストールを案内します。$\r$\n$\r$\nアンインストールを開始する前に、Geometry Dashが実行されていないことを確認してください。$\r$\n$\r$\n$_CLICK"
${LangFileString} MUI_TEXT_WELCOME_INFO_TEXT "このセットアップは$(^NameDA)のインストールを案内します。$\r$\n$\r$\nインストールを開始する前に、Geometry Dashが実行されていないことを確認してください。$\r$\n$\r$\n$_CLICK"
${LangFileString} MUI_UNTEXT_WELCOME_INFO_TEXT "このセットアップは$(^NameDA)のアンインストールを案内します。$\r$\n$\r$\nアンインストールを開始する前に、Geometry Dashが実行されていないことを確認してください。$\r$\n$\r$\n$_CLICK"
!pragma warning default 6030
; installer

View file

@ -0,0 +1,16 @@
!insertmacro LANGFILE_EXT SimpChinese
!pragma warning disable 6030
${LangFileString} MUI_TEXT_WELCOME_INFO_TEXT "Setup会帮您安装$(^NameDA)。$\r$\n$\r$\n安装Geode之前请确认Geometry Dash已经关闭。$\r$\n$\r$\n$_CLICK"
${LangFileString} MUI_UNTEXT_WELCOME_INFO_TEXT "Setup会帮您卸载$(^NameDA)。$\r$\n$\r$\n卸载Geode之前请确认Geometry Dash已经关闭。$\r$\n$\r$\n$_CLICK"
!pragma warning default 6030
; installer
${LangFileString} GEODE_TEXT_GD_MISSING "$\r$\n$\r$\nGeometry Dash不在这文件目录请再试一遍"
${LangFileString} GEODE_TEXT_MH_ALREADY_INSTALLED "这文件目录已经安装了Mega Hack v6/v7$\r$\nGeode不能跟MHv6/v7一起用(可是MHv8可以跟Geode一起用)。$\r$\n请先卸载MHv6/v7。"
${LangFileString} GEODE_TEXT_MOD_LOADER_ALREADY_INSTALLED "这文件目录已经安装了不同的游戏修改器加载器!$\r$\nGeode不能和不同的游戏修改器加载器一起用。$\r$\n请先卸载那个游戏修改器加载器。 (the dll trademark)"
; uninstaller
${LangFileString} GEODE_UNTEXT_GEODE_MISSING "Geode不在这文件目录请再试一遍"

View file

@ -1,15 +1,15 @@
!insertmacro LANGFILE_EXT Spanish
!pragma warning disable 6030
${LangFileString} MUI_TEXT_WELCOME_INFO_TEXT "Este asistente te guiará durante la instalación de $(^NameDA) en tu ordenador.$\r$\n$\r$\nAntes de comenzar la instalación, asegúrate de que Geometry Dash no se esté ejecutando.$\r$\n$\r$\n$_CLICK"
${LangFileString} MUI_UNTEXT_WELCOME_INFO_TEXT "Este asistente te guiará durante la desinstalación de $(^NameDA).$\r$\n$\r$\nAntes de comenzar la desinstalación, asegúrate de que Geometry Dash no se esté ejecutando.$\r$\n$\r$\n$_CLICK"
${LangFileString} MUI_TEXT_WELCOME_INFO_TEXT "Este asistente te guiará durante la instalación de $(^NameDA) en tu ordenador.$\r$\n$\r$\nAntes de comenzar la instalación, asegúrate de que Geometry Dash no esté en ejecución.$\r$\n$\r$\n$_CLICK"
${LangFileString} MUI_UNTEXT_WELCOME_INFO_TEXT "Este asistente te guiará durante la desinstalación de $(^NameDA).$\r$\n$\r$\nAntes de comenzar la desinstalación, asegúrate de que Geometry Dash no esté en ejecución.$\r$\n$\r$\n$_CLICK"
!pragma warning default 6030
; instalador
${LangFileString} GEODE_TEXT_GD_MISSING "$\r$\n$\r$\n¡Geometry Dash no está instalado en esta ruta!"
${LangFileString} GEODE_TEXT_MH_ALREADY_INSTALLED "¡Mega Hack v6/v7 está instalado en esta ruta!$\r$\nGeode no es compatible con MHv6/v7 (MHv8 será compatible con Geode).$\r$\nPor favor, desinstálalo antes de seguir."
${LangFileString} GEODE_TEXT_MOD_LOADER_ALREADY_INSTALLED "¡Hay otro cargador de mods instalado en esta ruta!$\r$\nGeode no funciona con ningún otro cargador de mods.$\r$\nPor favor, desinstálalo antes de seguir. (the dll trademark)"
${LangFileString} GEODE_TEXT_MH_ALREADY_INSTALLED "¡Mega Hack v6/v7 está instalado en esta ruta!$\r$\nGeode no es compatible con MHv6/v7 (MHv8 será compatible con Geode).$\r$\nPor favor, desinstálalo antes de continuar."
${LangFileString} GEODE_TEXT_MOD_LOADER_ALREADY_INSTALLED "¡Hay otro cargador de mods instalado en esta ruta!$\r$\nGeode no funciona con ningún otro cargador de mods.$\r$\nPor favor, desinstálalo antes de continuar. (the dll trademark)"
; desinstalador

View file

@ -0,0 +1,16 @@
!insertmacro LANGFILE_EXT TradChinese
!pragma warning disable 6030
${LangFileString} MUI_TEXT_WELCOME_INFO_TEXT "Setup會幫您安裝$(^NameDA)。$\r$\n$\r$\n安裝Geode之前請確認Geometry Dash已經關閉。$\r$\n$\r$\n$_CLICK"
${LangFileString} MUI_UNTEXT_WELCOME_INFO_TEXT "Setup會幫您卸載$(^NameDA)。$\r$\n$\r$\n卸載Geode之前請確認Geometry Dash已經關閉。$\r$\n$\r$\n$_CLICK"
!pragma warning default 6030
; installer
${LangFileString} GEODE_TEXT_GD_MISSING "$\r$\n$\r$\nGeometry Dash不在這文件目錄請再試一遍"
${LangFileString} GEODE_TEXT_MH_ALREADY_INSTALLED "這文件目錄已經安裝了Mega Hack v6/v7$\r$\nGeode不能跟MHv6/v7一起用(可是MHv8可以跟Geode一起用)。$\r$\n請先卸載MHv6/v7。"
${LangFileString} GEODE_TEXT_MOD_LOADER_ALREADY_INSTALLED "這文件目錄已經安裝了不同的遊戲修改器加載器!$\r$\nGeode不能跟不同的遊戲修改器加載器一起用。$\r$\n請先卸載那個遊戲修改器加載器。 (the dll trademark)"
; uninstaller
${LangFileString} GEODE_UNTEXT_GEODE_MISSING "Geode不在這文件目錄請再試一遍"

View file

@ -0,0 +1,16 @@
!insertmacro LANGFILE_EXT Ukrainian
!pragma warning disable 6030
${LangFileString} MUI_TEXT_WELCOME_INFO_TEXT "Ця програма допоможе вам встановити $(^NameDA).$\r$\n$\r$\nПеред початком встановлення переконайтеся, що Geometry Dash не запущено.$\r$\n$\r$\n$_CLICK"
${LangFileString} MUI_UNTEXT_WELCOME_INFO_TEXT "Ця програма допоможе вам видалити $(^NameDA).$\r$\n$\r$\nПеред початком видалення переконайтеся, що Geometry Dash не запущено.$\r$\n$\r$\n$_CLICK"
!pragma warning default 6030
; installer
${LangFileString} GEODE_TEXT_GD_MISSING "$\r$\n$\r$\nУ цій теці не встановлено Geometry Dash!"
${LangFileString} GEODE_TEXT_MH_ALREADY_INSTALLED "Ця тека вже містить Mega Hack v6/v7!$\r$\nGeode не працює з MHv6/v7 (MHv8 буде сумісний з Geode).$\r$\nБудь ласка, видаліть його перед продовженням."
${LangFileString} GEODE_TEXT_MOD_LOADER_ALREADY_INSTALLED "Ця тека вже містить інший завантажувач модів!$\r$\nGeode не працює з іншими завантажувачами модів.$\r$\nБудь ласка, видаліть його перед продовженням. (the dll trademark)"
; uninstaller
${LangFileString} GEODE_UNTEXT_GEODE_MISSING "У цій теці не встановлено Geode!"

View file

@ -46,15 +46,20 @@
; TODO: add the commented out languages (other available languages are listed here: https://nsis.sourceforge.io/Examples/Modern%20UI/MultiLanguage.nsi)
!insertmacro GEODE_LANGUAGE "English"
!insertmacro GEODE_LANGUAGE "French"
!insertmacro GEODE_LANGUAGE "Spanish"
!insertmacro GEODE_LANGUAGE "SpanishInternational"
;!insertmacro GEODE_LANGUAGE "Swedish"
!insertmacro GEODE_LANGUAGE "Swedish"
!insertmacro GEODE_LANGUAGE "Greek"
!insertmacro GEODE_LANGUAGE "Finnish"
!insertmacro GEODE_LANGUAGE "Russian"
!insertmacro GEODE_LANGUAGE "PortugueseBR"
!insertmacro GEODE_LANGUAGE "Ukrainian"
!insertmacro GEODE_LANGUAGE "Czech"
!insertmacro GEODE_LANGUAGE "Turkish"
!insertmacro GEODE_LANGUAGE "Japanese"
!insertmacro GEODE_LANGUAGE "SimpChinese"
!insertmacro GEODE_LANGUAGE "TradChinese"
!insertmacro MUI_RESERVEFILE_LANGDLL

View file

@ -12,9 +12,15 @@ else()
endif()
if (GEODE_VERSION_TAG)
set(PROJECT_VERSION_SUFFIX "-${GEODE_VERSION_TAG}")
set(PROJECT_VERSION_SUFFIX "-${GEODE_VERSION_TAG}" CACHE INTERNAL "" )
else()
set(PROJECT_VERSION_SUFFIX "")
set(PROJECT_VERSION_SUFFIX "" CACHE INTERNAL "" )
endif()
# I think CMake is trying to link zlib from the host system?
# This prevents it from doing that.
if (WIN32 AND CMAKE_CROSSCOMPILING)
set(MZ_FORCE_FETCH_LIBS ON)
endif()
# https://stackoverflow.com/a/63924044/9124836

View file

@ -4,7 +4,7 @@ struct TodoReturnPlaceholder;
#ifdef GEODE_REVERT_TODO_RETURN
using TodoReturn = void;
#warning "Reverting TodoReturn to void. This behavior is deprecated and will be removed in a later update."
#pragma message("Reverting TodoReturn to void. This behavior is deprecated and will be removed in a later update.")
#else
#define GEODE_REVERT_TODO_RETURN 0
using TodoReturn = TodoReturnPlaceholder;
@ -337,6 +337,7 @@ enum class ShopType {
// Geode Addition
enum class ZLayer {
B5 = -5,
B4 = -3,
B3 = -1,
B2 = 1,
@ -345,6 +346,7 @@ enum class ZLayer {
T1 = 5,
T2 = 7,
T3 = 9,
T4 = 11,
};
enum class UpdateResponse {
@ -524,7 +526,8 @@ enum class GJChallengeType {
Unknown = 0,
Orbs = 1,
UserCoins = 2,
Stars = 3
Stars = 3,
Moons = 4,
};
enum class GJScoreType {

View file

@ -48,7 +48,9 @@ struct _ListIterTypes {
using _Nodeptr = _Nodeptr_type;
};
#if _ITERATOR_DEBUG_LEVEL == 0
using _STD _Fake_alloc;
#endif
// The following types are not accessible from std::list.
template <class _Ty, class _Alloc = _STD allocator<_Ty>>

View file

@ -862,7 +862,9 @@ public:
private:
friend class geode::modifier::FieldContainer;
[[deprecated("Will be removed, it's an ABI break")]]
GEODE_DLL geode::modifier::FieldContainer* getFieldContainer();
GEODE_DLL geode::modifier::FieldContainer* getFieldContainer(char const* forClass);
GEODE_DLL void addEventListenerInternal(
std::string const& id,
geode::EventListenerProtocol* protocol

View file

@ -433,7 +433,9 @@ namespace geode {
bool isLoggingEnabled() const;
void setLoggingEnabled(bool enabled);
bool hasProblems() const;
bool shouldLoad() const;
bool isCurrentlyLoading() const;
friend class ModImpl;
};

View file

@ -44,8 +44,8 @@ namespace geode::modifier {
return m_containedFields.at(index);
}
static FieldContainer* from(cocos2d::CCNode* node) {
return node->getFieldContainer();
static FieldContainer* from(cocos2d::CCNode* node, char const* forClass) {
return node->getFieldContainer(forClass);
}
};
@ -97,7 +97,7 @@ namespace geode::modifier {
static_assert(sizeof(Base) == offsetof(Parent, m_fields), "offsetof not correct");
// generating the container if it doesn't exist
auto container = FieldContainer::from(node);
auto container = FieldContainer::from(node, typeid(Base).name());
// the index is global across all mods, so the
// function is defined in the loader source

View file

@ -26,7 +26,7 @@ namespace geode {
* - Lists
*
* Note that links also have some special protocols.
* Use `user:<id>` or `user:<name>` to link to a GD
* Use `user:<accountID>` to link to a GD
* account; `level:<id>` to link to a GD level and
* `mod:<id>` to link to another Geode mod.
*/
@ -48,6 +48,8 @@ namespace geode {
void onLink(CCObject*);
void onGDProfile(CCObject*);
void onGDLevel(CCObject*);
void onGeodeMod(CCObject*);
void FLAlert_Clicked(FLAlertLayer*, bool btn) override;
friend struct ::MDParser;

View file

@ -638,7 +638,7 @@ namespace geode::cocos {
template <class Type = cocos2d::CCNode>
static Type* getChildOfType(cocos2d::CCNode* node, int index) {
size_t indexCounter = 0;
if (node->getChildrenCount() == 0) return nullptr;
// start from end for negative index
if (index < 0) {
index = -index - 1;
@ -650,6 +650,7 @@ namespace geode::cocos {
}
++indexCounter;
}
if (i == 0) break;
}
}
else {

View file

@ -17,6 +17,7 @@ struct ProxyCCNode;
class GeodeNodeMetadata final : public cocos2d::CCObject {
private:
FieldContainer* m_fieldContainer;
std::unordered_map<std::string, FieldContainer*> m_classFieldContainers;
std::string m_id = "";
Ref<Layout> m_layout = nullptr;
Ref<LayoutOptions> m_layoutOptions = nullptr;
@ -62,6 +63,13 @@ public:
FieldContainer* getFieldContainer() {
return m_fieldContainer;
}
FieldContainer* getFieldContainer(char const* forClass) {
if (!m_classFieldContainers.count(forClass)) {
m_classFieldContainers[forClass] = new FieldContainer();
}
return m_classFieldContainers[forClass];
}
};
// proxy forwards
@ -99,6 +107,10 @@ FieldContainer* CCNode::getFieldContainer() {
return GeodeNodeMetadata::set(this)->getFieldContainer();
}
FieldContainer* CCNode::getFieldContainer(char const* forClass) {
return GeodeNodeMetadata::set(this)->getFieldContainer(forClass);
}
std::string CCNode::getID() {
return GeodeNodeMetadata::set(this)->m_id;
}

View file

@ -146,13 +146,27 @@ struct CustomLoadingLayer : Modify<CustomLoadingLayer, LoadingLayer> {
LoaderImpl::get()->updateResources(true);
this->continueLoadAssets();
}
int getLoadedMods() {
auto allMods = Loader::get()->getAllMods();
return std::count_if(allMods.begin(), allMods.end(), [&](auto& item) {
return item->isEnabled();
});
}
int getEnabledMods() {
auto allMods = Loader::get()->getAllMods();
return std::count_if(allMods.begin(), allMods.end(), [&](auto& item) {
return item->shouldLoad();
});
}
int getCurrentStep() {
return m_fields->m_geodeLoadStep + m_loadStep + 1 + LoaderImpl::get()->m_refreshedModCount;
return m_fields->m_geodeLoadStep + m_loadStep + getLoadedMods();
}
int getTotalStep() {
return 18 + m_fields->m_totalMods;
return 3 + 14 + getEnabledMods();
}
void updateLoadingBar() {

View file

@ -0,0 +1,46 @@
#include <Geode/Geode.hpp>
#ifdef GEODE_IS_WINDOWS
using namespace geode::prelude;
// https://github.com/cocos2d/cocos2d-x/blob/5a25fe75cb8b26b61b14b070e757ec3b17ff7791/cocos2dx/platform/win32/CCImage.cpp#L96
// stop setFont from caching fonts on Windows
// Windows Font Cache Manager holds on to them after the app has closed
// Fonts are supposed to be released in the BitmapDC::~BitmapDC() but this doesn't seem to work consistently?
// Looks like there's a shared instance of BitmapDC, so presumably it's destructed when the app closes?
int __stdcall AddFontResourceWHook(LPCWSTR p0) {
return AddFontResourceExW(p0, FR_PRIVATE, 0);
}
int __stdcall RemoveFontResourceWHook(LPCWSTR p0) {
return RemoveFontResourceExW(p0, FR_PRIVATE, 0);
}
/*
* addr is relative to cocos base
* patches x86 CALL at addr to call function at newCall
*/
static void patchCall(uintptr_t addr, uintptr_t newCall) {
ByteVector patch = { 0xE8 }; // CALL near & relative
addr += (uintptr_t)geode::base::getCocos();
uintptr_t callAddr = newCall - (addr + 5);
for (auto i = 0; i < sizeof(int); ++i)
patch.push_back(callAddr >> (8 * i));
patch.push_back(0x90); // every overwritten instruction happens to be 6 bytes wide
(void)Mod::get()->patch(reinterpret_cast<void*>(addr), patch);
}
$execute {
// BitmapDC::~BitmapDC
patchCall(0xC9A56, (uintptr_t)&RemoveFontResourceWHook);
// BitmapDC::setFont
patchCall(0xCB5BC, (uintptr_t)&RemoveFontResourceWHook);
patchCall(0xCB642, (uintptr_t)&AddFontResourceWHook);
};
#endif

View file

@ -3,9 +3,9 @@
#include <Geode/utils/VersionInfo.hpp>
namespace about {
geode::VersionInfo getLoaderVersion();
const char* getLoaderVersionStr();
const char* getLoaderCommitHash();
const char* getBindingsCommitHash();
const char* getLoaderModJson();
GEODE_DLL geode::VersionInfo getLoaderVersion();
GEODE_DLL const char* getLoaderVersionStr();
GEODE_DLL const char* getLoaderCommitHash();
GEODE_DLL const char* getBindingsCommitHash();
GEODE_DLL const char* getLoaderModJson();
};

View file

@ -42,9 +42,9 @@ void crashlog::printMods(std::stringstream& stream) {
using namespace std::string_view_literals;
for (auto& mod : mods) {
stream << fmt::format("{} | [{}] {}\n",
ModImpl::getImpl(mod)->isCurrentlyLoading() ? "o"sv :
mod->isCurrentlyLoading() ? "o"sv :
mod->isEnabled() ? "x"sv :
ModImpl::getImpl(mod)->hasProblems() ? "!"sv : // thank you for this bug report
mod->hasProblems() ? "!"sv : // thank you for this bug report
mod->shouldLoad() ? "~"sv :
" "sv,
mod->getVersion().toString(), mod->getID()

View file

@ -35,8 +35,8 @@ namespace crashlog {
std::string getDateString(bool filesafe);
void printGeodeInfo(std::stringstream& stream);
void printMods(std::stringstream& stream);
void GEODE_DLL printGeodeInfo(std::stringstream& stream);
void GEODE_DLL printMods(std::stringstream& stream);
}

View file

@ -241,6 +241,14 @@ bool Mod::hasSavedValue(std::string_view const key) {
return this->getSaveContainer().contains(key);
}
bool Mod::hasProblems() const {
return m_impl->hasProblems();
}
bool Mod::shouldLoad() const {
return m_impl->shouldLoad();
}
bool Mod::isCurrentlyLoading() const {
return m_impl->isCurrentlyLoading();
}

View file

@ -59,8 +59,7 @@ Result<> Mod::Impl::setup() {
}
if (!m_resourcesLoaded) {
auto searchPathRoot = dirs::getModRuntimeDir() / m_metadata.getID() / "resources";
// TODO: why is this commented out
// CCFileUtils::get()->addSearchPath(searchPathRoot.string().c_str());
CCFileUtils::get()->addSearchPath(searchPathRoot.string().c_str());
const auto binariesDir = searchPathRoot / m_metadata.getID() / "binaries" / PlatformID::toShortString(GEODE_PLATFORM_TARGET);
if (ghc::filesystem::exists(binariesDir))
@ -632,16 +631,16 @@ Result<> Mod::Impl::disownPatch(Patch* patch) {
"A patch that was getting disowned had its owner set but the owner "
"didn't have the patch in m_patches.");
m_patches.erase(foundIt);
if (!this->isEnabled() || !patch->getAutoEnable())
return Ok();
auto res2 = patch->disable();
if (!res2) {
return Err("Cannot disable patch: {}", res2.unwrapErr());
if (this->isEnabled() && patch->getAutoEnable()) {
auto res2 = patch->disable();
if (!res2) {
return Err("Cannot disable patch: {}", res2.unwrapErr());
}
}
m_patches.erase(foundIt);
return Ok();
}

View file

@ -70,8 +70,15 @@ Result<> Patch::Impl::enable() {
Result<> Patch::Impl::disable() {
auto res = tulip::hook::writeMemory(m_address, m_original.data(), m_original.size());
if (!res) return Err("Failed to disable patch: {}", res.unwrapErr());
m_enabled = false;
allEnabled().erase(std::find(allEnabled().begin(), allEnabled().end(), this));
auto it = std::find(allEnabled().begin(), allEnabled().end(), this);
if (it == allEnabled().end()) {
return Err("Failed to disable patch: patch is already disabled");
}
allEnabled().erase(it);
return Ok();
}

View file

@ -1,6 +1,12 @@
#include <Geode/binding/ProfilePage.hpp>
#include <Geode/binding/LevelTools.hpp>
#include <Geode/binding/LevelInfoLayer.hpp>
#include <Geode/binding/CCContentLayer.hpp>
#include <Geode/binding/GJSearchObject.hpp>
#include <Geode/binding/LevelBrowserLayer.hpp>
#include <Geode/loader/Mod.hpp>
#include <Geode/loader/Loader.hpp>
#include <Geode/loader/Index.hpp>
#include <Geode/ui/MDTextArea.hpp>
#include <Geode/utils/casts.hpp>
#include <Geode/utils/cocos.hpp>
@ -10,6 +16,7 @@
#include <md4c.h>
#include <charconv>
#include <Geode/loader/Log.hpp>
#include "../internal/info/ModInfoPopup.hpp"
using namespace geode::prelude;
@ -192,7 +199,7 @@ void MDTextArea::onGDProfile(CCObject* pSender) {
"Error",
"Invalid profile ID: <cr>" + profile +
"</c>. This is "
"probably the modder's fault, report the bug to them.",
"probably the mod developer's fault, report the bug to them.",
"OK"
)
->show();
@ -201,6 +208,67 @@ void MDTextArea::onGDProfile(CCObject* pSender) {
ProfilePage::create(id, false)->show();
}
void MDTextArea::onGDLevel(CCObject* pSender) {
auto href = as<CCString*>(as<CCNode*>(pSender)->getUserObject());
auto level = std::string(href->getCString());
level = level.substr(level.find(":") + 1);
int id = 0;
auto res = std::from_chars(level.data(), level.data() + level.size(), id);
if (res.ec != std::errc()) {
FLAlertLayer::create(
"Error",
"Invalid level ID: <cr>" + level +
"</c>. This is "
"probably the mod developers's fault, report the bug to them.",
"OK"
)
->show();
return;
}
auto searchObject = GJSearchObject::create(SearchType::Type19, fmt::format("{}&gameVersion=22", id));
auto scene = LevelBrowserLayer::scene(searchObject);
CCDirector::sharedDirector()->replaceScene(CCTransitionFade::create(0.5f, scene));
}
void MDTextArea::onGeodeMod(CCObject* pSender) {
auto href = as<CCString*>(as<CCNode*>(pSender)->getUserObject());
auto modString = std::string(href->getCString());
modString = modString.substr(modString.find(":") + 1);
auto loader = Loader::get();
auto index = Index::get();
Mod* mod;
bool success = false;
IndexItemHandle indexItem;
bool isIndexMod = !loader->isModInstalled(modString);
if (isIndexMod) {
auto indexSearch = index->getItemsByModID(modString);
if (indexSearch.size() != 0) {
indexItem = indexSearch.back();
Mod mod2 = Mod(indexItem->getMetadata());
mod = &mod2;
auto item = Index::get()->getItem(mod);
IndexItemInfoPopup::create(item, nullptr)->show();
success = true;
}
} else {
mod = loader->getLoadedMod(modString);
LocalModInfoPopup::create(mod, nullptr)->show();
success = true;
}
if (!success) {
FLAlertLayer::create(
"Error",
"Invalid mod ID: <cr>" + modString +
"</c>. This is "
"probably the mod developers's fault, report the bug to them.",
"OK"
)
->show();
}
}
void MDTextArea::FLAlert_Clicked(FLAlertLayer* layer, bool btn) {
if (btn) {
web::openLinkInBrowser(as<CCString*>(layer->getUserObject())->getCString());
@ -243,7 +311,7 @@ struct MDParser {
case MD_TEXTTYPE::MD_TEXT_SOFTBR:
{
renderer->breakLine();
renderer->renderString(" ");
}
break;
@ -256,7 +324,11 @@ struct MDParser {
text, textarea,
utils::string::startsWith(s_lastLink, "user:")
? menu_selector(MDTextArea::onGDProfile)
: menu_selector(MDTextArea::onLink)
: utils::string::startsWith(s_lastLink, "level:")
? menu_selector(MDTextArea::onGDLevel)
: utils::string::startsWith(s_lastLink, "mod:")
? menu_selector(MDTextArea::onGeodeMod)
: menu_selector(MDTextArea::onLink)
);
for (auto const& label : rendered) {
label.m_node->setUserObject(CCString::create(s_lastLink));

View file

@ -12,4 +12,5 @@ add_compile_definitions(EXPORTING_MOD)
set(GEODE_LINK_SOURCE ON)
set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "")
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/mod.json.in ${CMAKE_CURRENT_SOURCE_DIR}/mod.json)
create_geode_file(${PROJECT_NAME} DONT_INSTALL)

View file

@ -1,5 +1,5 @@
{
"geode": "2.0.0",
"geode": "@GEODE_VERSION_FULL@",
"gd": "*",
"version": "1.0.0",
"id": "geode.testdep",

View file

@ -11,4 +11,5 @@ set(GEODE_LINK_SOURCE ON)
set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "")
target_link_libraries(TestMod TestDependency)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/mod.json.in ${CMAKE_CURRENT_SOURCE_DIR}/mod.json)
setup_geode_mod(${PROJECT_NAME} DONT_INSTALL)

View file

@ -1,5 +1,5 @@
{
"geode": "2.0.0",
"geode": "@GEODE_VERSION_FULL@",
"gd": "*",
"version": "1.0.0",
"id": "geode.test",