mirror of
https://github.com/geode-sdk/geode.git
synced 2024-11-14 19:15:05 -05:00
Merge branch 'main' of github.com:geode-sdk/geode into web-request-refactor
This commit is contained in:
commit
8081860055
39 changed files with 307 additions and 453 deletions
|
@ -7,10 +7,9 @@ if (GEODE_BUILDING_DOCS)
|
|||
set(GEODE_DISABLE_CLI_CALLS On)
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS On)
|
||||
set(GEODE_DISABLE_PRECOMPILED_HEADERS On)
|
||||
set(GEODE_DONT_BUILD_TEST_MODS On)
|
||||
endif()
|
||||
|
||||
set(GEODE_GD_VERSION 2.200)
|
||||
|
||||
# Read version
|
||||
file(READ VERSION GEODE_VERSION)
|
||||
string(STRIP "${GEODE_VERSION}" GEODE_VERSION)
|
||||
|
@ -77,8 +76,19 @@ include(cmake/Platform.cmake)
|
|||
include(cmake/GeodeFile.cmake)
|
||||
include(cmake/CPM.cmake)
|
||||
|
||||
if (NOT DEFINED GEODE_GD_VERSION)
|
||||
if (${GEODE_TARGET_PLATFORM} STREQUAL "Win32")
|
||||
set(GEODE_GD_VERSION 2.202)
|
||||
else()
|
||||
set(GEODE_GD_VERSION 2.200)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
target_compile_definitions(${PROJECT_NAME} INTERFACE GEODE_GD_VERSION=${GEODE_GD_VERSION})
|
||||
|
||||
|
||||
set(MAT_JSON_AS_INTERFACE ON)
|
||||
CPMAddPackage("gh:geode-sdk/json#9f54cca")
|
||||
CPMAddPackage("gh:geode-sdk/json#49bdff7")
|
||||
CPMAddPackage("gh:fmtlib/fmt#10.1.1")
|
||||
CPMAddPackage("gh:gulrak/filesystem#3e5b930")
|
||||
|
||||
|
|
|
@ -1,22 +1,4 @@
|
|||
if (NOT DEFINED GEODE_TARGET_PLATFORM)
|
||||
if(APPLE)
|
||||
if(IOS)
|
||||
set(GEODE_TARGET_PLATFORM "iOS")
|
||||
else()
|
||||
set(GEODE_TARGET_PLATFORM "MacOS")
|
||||
endif()
|
||||
elseif(WIN32)
|
||||
set(GEODE_TARGET_PLATFORM "Win32")
|
||||
elseif(ANDROID)
|
||||
if (ANDROID_ABI STREQUAL "arm64-v8a")
|
||||
set(GEODE_TARGET_PLATFORM "Android64")
|
||||
elseif(ANDROID_ABI STREQUAL "armeabi-v7a")
|
||||
set(GEODE_TARGET_PLATFORM "Android32")
|
||||
endif()
|
||||
else()
|
||||
message(FATAL_ERROR "Unable to detect platform, please set GEODE_TARGET_PLATFORM in the root CMake file.")
|
||||
endif()
|
||||
endif()
|
||||
include(cmake/PlatformDetect.cmake)
|
||||
|
||||
if (NOT ${PROJECT_NAME} STREQUAL ${CMAKE_PROJECT_NAME})
|
||||
set(GEODE_TARGET_PLATFORM GEODE_TARGET_PLATFORM PARENT_SCOPE)
|
||||
|
|
19
cmake/PlatformDetect.cmake
Normal file
19
cmake/PlatformDetect.cmake
Normal file
|
@ -0,0 +1,19 @@
|
|||
if (NOT DEFINED GEODE_TARGET_PLATFORM)
|
||||
if(APPLE)
|
||||
if(IOS)
|
||||
set(GEODE_TARGET_PLATFORM "iOS")
|
||||
else()
|
||||
set(GEODE_TARGET_PLATFORM "MacOS")
|
||||
endif()
|
||||
elseif(WIN32)
|
||||
set(GEODE_TARGET_PLATFORM "Win32")
|
||||
elseif(ANDROID)
|
||||
if (ANDROID_ABI STREQUAL "arm64-v8a")
|
||||
set(GEODE_TARGET_PLATFORM "Android64")
|
||||
elseif(ANDROID_ABI STREQUAL "armeabi-v7a")
|
||||
set(GEODE_TARGET_PLATFORM "Android32")
|
||||
endif()
|
||||
else()
|
||||
message(FATAL_ERROR "Unable to detect platform, please set GEODE_TARGET_PLATFORM in the root CMake file.")
|
||||
endif()
|
||||
endif()
|
|
@ -11,7 +11,11 @@ icon = "loader/resources/logos/geode-circle.png"
|
|||
|
||||
[tutorials]
|
||||
dir = "docs"
|
||||
assets = ["docs/assets/*.png"]
|
||||
assets = [
|
||||
"docs/assets/*.png",
|
||||
"docs/assets/handbook/vol1/*.png",
|
||||
"docs/assets/handbook/vol2/*.png",
|
||||
]
|
||||
|
||||
[[sources]]
|
||||
name = "Geode"
|
||||
|
|
|
@ -26,6 +26,22 @@ execute_process(
|
|||
ERROR_QUIET
|
||||
)
|
||||
|
||||
if (NOT GEODE_COMMIT_HASH)
|
||||
set(GEODE_COMMIT_HASH "(?)")
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND git rev-parse --short HEAD
|
||||
WORKING_DIRECTORY ${GEODE_BINDINGS_REPO_PATH}
|
||||
OUTPUT_VARIABLE GEODE_BINDINGS_COMMIT_HASH
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_QUIET
|
||||
)
|
||||
|
||||
if (NOT GEODE_BINDINGS_COMMIT_HASH)
|
||||
set(GEODE_BINDINGS_COMMIT_HASH "(?)")
|
||||
endif()
|
||||
|
||||
# Package info file for internal representation
|
||||
set(GEODE_RESOURCES_PATH ${CMAKE_CURRENT_SOURCE_DIR}/resources)
|
||||
configure_file(resources/mod.json.in ${CMAKE_CURRENT_SOURCE_DIR}/resources/mod.json)
|
||||
|
@ -53,8 +69,6 @@ file(GLOB SOURCES CONFIGURE_DEPENDS
|
|||
src/ui/*.cpp
|
||||
src/ui/nodes/*.cpp
|
||||
src/ui/internal/*.cpp
|
||||
src/ui/internal/credits/*.cpp
|
||||
src/ui/internal/dev/*.cpp
|
||||
src/ui/internal/info/*.cpp
|
||||
src/ui/internal/list/*.cpp
|
||||
src/ui/internal/settings/*.cpp
|
||||
|
@ -277,6 +291,3 @@ elseif (WIN32)
|
|||
endif()
|
||||
|
||||
add_subdirectory(test)
|
||||
|
||||
# Build index hashing algorithm test program
|
||||
add_subdirectory(hash)
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
cmake_minimum_required(VERSION 3.21 FATAL_ERROR)
|
||||
|
||||
project(GeodeChecksum VERSION 1.0)
|
||||
|
||||
add_executable(${PROJECT_NAME} main.cpp hash.cpp)
|
||||
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_20)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC ghc_filesystem)
|
||||
|
||||
message(STATUS "Building Checksum Exe")
|
|
@ -1,11 +0,0 @@
|
|||
#include <iostream>
|
||||
#include "hash.hpp"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (argc < 2 || !ghc::filesystem::exists(argv[1])) {
|
||||
std::cout << "Usage: \"checksum <file>\"\n";
|
||||
return 1;
|
||||
}
|
||||
std::cout << calculateHash(argv[1]) << std::endl;
|
||||
return 0;
|
||||
}
|
|
@ -42,7 +42,6 @@ enum class SearchType {
|
|||
FavouriteLists = 103
|
||||
};
|
||||
|
||||
// jesus fucking christ (painfully written by @hjfod)
|
||||
enum class GameObjectType {
|
||||
Solid = 0,
|
||||
Hazard = 2,
|
||||
|
@ -287,6 +286,11 @@ enum class SpecialRewardItem {
|
|||
Orbs = 0x7,
|
||||
Diamonds = 0x8,
|
||||
CustomItem = 0x9,
|
||||
EarthShard = 0xA,
|
||||
BloodShard = 0xB,
|
||||
MetalShard = 0xC,
|
||||
LightShard = 0xD,
|
||||
SoulShard = 0xE
|
||||
};
|
||||
|
||||
enum class EditCommand {
|
||||
|
|
|
@ -417,7 +417,6 @@ public:
|
|||
* @note For internal usage, we need to declare this member variable as public since it's used in UT_HASH.
|
||||
*/
|
||||
CCDictElement* m_pElements;
|
||||
private:
|
||||
|
||||
/** The support type of dictionary, it's confirmed when setObject is invoked. */
|
||||
enum CCDictType
|
||||
|
|
|
@ -90,12 +90,12 @@ namespace geode {
|
|||
ModMetadata getMetadata() const;
|
||||
ghc::filesystem::path getTempDir() const;
|
||||
/**
|
||||
* Get the path to the mod's platform binary (.dll on Windows, .dylib
|
||||
* Get the path to the mod's platform binary (.dll on Windows, .dylib
|
||||
* on Mac & iOS, .so on Android)
|
||||
*/
|
||||
ghc::filesystem::path getBinaryPath() const;
|
||||
/**
|
||||
* Get the path to the mod's runtime resources directory (contains all
|
||||
* Get the path to the mod's runtime resources directory (contains all
|
||||
* of its resources)
|
||||
*/
|
||||
ghc::filesystem::path getResourcesDir() const;
|
||||
|
@ -119,25 +119,25 @@ namespace geode {
|
|||
|
||||
bool hasSettings() const;
|
||||
std::vector<std::string> getSettingKeys() const;
|
||||
bool hasSetting(std::string const& key) const;
|
||||
std::optional<Setting> getSettingDefinition(std::string const& key) const;
|
||||
SettingValue* getSetting(std::string const& key) const;
|
||||
bool hasSetting(std::string_view const key) const;
|
||||
std::optional<Setting> getSettingDefinition(std::string_view const key) const;
|
||||
SettingValue* getSetting(std::string_view const key) const;
|
||||
|
||||
/**
|
||||
* Register a custom setting's value class. See Mod::addCustomSetting
|
||||
* for a convenience wrapper that creates the value in-place to avoid
|
||||
* code duplication. Also see
|
||||
* [the tutorial page](https://docs.geode-sdk.org/mods/settings) for
|
||||
* Register a custom setting's value class. See Mod::addCustomSetting
|
||||
* for a convenience wrapper that creates the value in-place to avoid
|
||||
* code duplication. Also see
|
||||
* [the tutorial page](https://docs.geode-sdk.org/mods/settings) for
|
||||
* more information about custom settings
|
||||
* @param key The setting's key
|
||||
* @param value The SettingValue class that shall handle this setting
|
||||
* @see addCustomSetting
|
||||
*/
|
||||
void registerCustomSetting(std::string const& key, std::unique_ptr<SettingValue> value);
|
||||
void registerCustomSetting(std::string_view const key, std::unique_ptr<SettingValue> value);
|
||||
/**
|
||||
* Register a custom setting's value class. The new SettingValue class
|
||||
* will be created in-place using `std::make_unique`. See
|
||||
* [the tutorial page](https://docs.geode-sdk.org/mods/settings) for
|
||||
* Register a custom setting's value class. The new SettingValue class
|
||||
* will be created in-place using `std::make_unique`. See
|
||||
* [the tutorial page](https://docs.geode-sdk.org/mods/settings) for
|
||||
* more information about custom settings
|
||||
* @param key The setting's key
|
||||
* @param value The value of the custom setting
|
||||
|
@ -147,14 +147,14 @@ namespace geode {
|
|||
* }
|
||||
*/
|
||||
template <class T, class V>
|
||||
void addCustomSetting(std::string const& key, V const& value) {
|
||||
this->registerCustomSetting(key, std::make_unique<T>(key, this->getID(), value));
|
||||
void addCustomSetting(std::string_view const key, V const& value) {
|
||||
this->registerCustomSetting(key, std::make_unique<T>(std::string(key), this->getID(), value));
|
||||
}
|
||||
|
||||
matjson::Value& getSaveContainer();
|
||||
|
||||
template <class T>
|
||||
T getSettingValue(std::string const& key) const {
|
||||
T getSettingValue(std::string_view const key) const {
|
||||
if (auto sett = this->getSetting(key)) {
|
||||
return SettingValueSetter<T>::get(sett);
|
||||
}
|
||||
|
@ -162,7 +162,7 @@ namespace geode {
|
|||
}
|
||||
|
||||
template <class T>
|
||||
T setSettingValue(std::string const& key, T const& value) {
|
||||
T setSettingValue(std::string_view const key, T const& value) {
|
||||
if (auto sett = this->getSetting(key)) {
|
||||
auto old = this->getSettingValue<T>(key);
|
||||
SettingValueSetter<T>::set(sett, value);
|
||||
|
@ -171,10 +171,10 @@ namespace geode {
|
|||
return T();
|
||||
}
|
||||
|
||||
bool hasSavedValue(std::string const& key);
|
||||
bool hasSavedValue(std::string_view const key);
|
||||
|
||||
template <class T>
|
||||
T getSavedValue(std::string const& key) {
|
||||
T getSavedValue(std::string_view const key) {
|
||||
auto& saved = this->getSaveContainer();
|
||||
if (saved.contains(key)) {
|
||||
try {
|
||||
|
@ -188,7 +188,7 @@ namespace geode {
|
|||
}
|
||||
|
||||
template <class T>
|
||||
T getSavedValue(std::string const& key, T const& defaultValue) {
|
||||
T getSavedValue(std::string_view const key, T const& defaultValue) {
|
||||
auto& saved = this->getSaveContainer();
|
||||
if (saved.contains(key)) {
|
||||
try {
|
||||
|
@ -210,7 +210,7 @@ namespace geode {
|
|||
* @returns The old value
|
||||
*/
|
||||
template <class T>
|
||||
T setSavedValue(std::string const& key, T const& value) {
|
||||
T setSavedValue(std::string_view const key, T const& value) {
|
||||
auto& saved = this->getSaveContainer();
|
||||
auto old = this->getSavedValue<T>(key);
|
||||
saved[key] = value;
|
||||
|
@ -335,7 +335,7 @@ namespace geode {
|
|||
* Check whether or not this Mod
|
||||
* depends on another mod
|
||||
*/
|
||||
bool depends(std::string const& id) const;
|
||||
bool depends(std::string_view const id) const;
|
||||
|
||||
/**
|
||||
* Check whether all the required
|
||||
|
|
|
@ -903,11 +903,33 @@ namespace geode::cocos {
|
|||
}
|
||||
};
|
||||
|
||||
template <typename _Type>
|
||||
template <class T>
|
||||
concept CocosObjectPtr = std::is_pointer_v<T> && std::is_convertible_v<T, cocos2d::CCObject const*>;
|
||||
|
||||
template <class K>
|
||||
concept CocosDictionaryKey = std::same_as<K, int> || std::same_as<K, intptr_t> || std::same_as<K, gd::string> || std::same_as<K, std::string>;
|
||||
|
||||
/**
|
||||
* A templated wrapper over CCArray, providing easy iteration and indexing.
|
||||
* This will keep ownership of the given CCArray*.
|
||||
*
|
||||
* @tparam Type Pointer to a type that inherits CCObject.
|
||||
*
|
||||
* @example
|
||||
* CCArrayExt<GameObject*> objects = PlayLayer::get()->m_objects;
|
||||
* // Easy indexing, giving you the type you assigned
|
||||
* GameObject* myObj = objects[2];
|
||||
*
|
||||
* // Easy iteration using C++ range-based for loops
|
||||
* for (auto* obj : objects) {
|
||||
* log::info("{}", obj->m_objectID);
|
||||
* }
|
||||
*/
|
||||
template <CocosObjectPtr Type>
|
||||
class CCArrayExt {
|
||||
protected:
|
||||
Ref<cocos2d::CCArray> m_arr;
|
||||
using T = std::remove_pointer_t<_Type>;
|
||||
using T = std::remove_pointer_t<Type>;
|
||||
|
||||
public:
|
||||
using value_type = T;
|
||||
|
@ -980,7 +1002,7 @@ namespace geode::cocos {
|
|||
cocos2d::CCDictElement* m_ptr;
|
||||
|
||||
std::pair<K, T> operator*() {
|
||||
if constexpr (std::is_same<K, std::string>::value) {
|
||||
if constexpr (std::is_same_v<K, std::string> || std::is_same_v<K, gd::string>) {
|
||||
return {m_ptr->getStrKey(), static_cast<T>(m_ptr->getObject())};
|
||||
}
|
||||
else {
|
||||
|
@ -1027,42 +1049,41 @@ namespace geode::cocos {
|
|||
}
|
||||
};
|
||||
|
||||
template <typename K, typename T>
|
||||
/**
|
||||
* A templated wrapper over CCDictionary, providing easy iteration and indexing.
|
||||
* This will keep ownership of the given CCDictionary*.
|
||||
*
|
||||
* @tparam Key Type of the key. MUST only be int or gd::string or std::string.
|
||||
* @tparam ValuePtr Pointer to a type that inherits CCObject.
|
||||
*
|
||||
* @example
|
||||
* CCDictionaryExt<std::string, GJGameLevel*> levels = getSomeDict();
|
||||
* // Easy indexing, giving you the type you assigned
|
||||
* GJGameLevel* myLvl = levels["Cube Adventures"];
|
||||
*
|
||||
* // Easy iteration using C++ range-based for loops
|
||||
* for (auto [name, level] : levels) {
|
||||
* log::info("{}: {}", name, level->m_levelID);
|
||||
* }
|
||||
*/
|
||||
template <CocosDictionaryKey Key, CocosObjectPtr ValuePtr>
|
||||
struct CCDictionaryExt {
|
||||
protected:
|
||||
cocos2d::CCDictionary* m_dict;
|
||||
Ref<cocos2d::CCDictionary> m_dict;
|
||||
|
||||
public:
|
||||
CCDictionaryExt() : m_dict(cocos2d::CCDictionary::create()) {
|
||||
m_dict->retain();
|
||||
}
|
||||
CCDictionaryExt() : m_dict(cocos2d::CCDictionary::create()) {}
|
||||
|
||||
CCDictionaryExt(cocos2d::CCDictionary* dict) : m_dict(dict) {
|
||||
m_dict->retain();
|
||||
}
|
||||
CCDictionaryExt(cocos2d::CCDictionary* dict) : m_dict(dict) {}
|
||||
|
||||
CCDictionaryExt(CCDictionaryExt const& d) : m_dict(d.m_dict) {
|
||||
m_dict->retain();
|
||||
}
|
||||
CCDictionaryExt(CCDictionaryExt const& d) : m_dict(d.m_dict) {}
|
||||
|
||||
CCDictionaryExt(CCDictionaryExt&& d) : m_dict(d.m_dict) {
|
||||
d.m_dict = nullptr;
|
||||
}
|
||||
|
||||
~CCDictionaryExt() {
|
||||
if (m_dict) m_dict->release();
|
||||
}
|
||||
|
||||
CCDictionaryExt& operator=(cocos2d::CCDictionary* d) {
|
||||
m_dict->release();
|
||||
m_dict = d;
|
||||
m_dict->retain();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto begin() {
|
||||
return CCDictIterator<K, T*>(m_dict->m_pElements);
|
||||
return CCDictIterator<Key, ValuePtr>(m_dict->m_pElements);
|
||||
}
|
||||
|
||||
// do not use this
|
||||
|
@ -1074,15 +1095,23 @@ namespace geode::cocos {
|
|||
return m_dict->count();
|
||||
}
|
||||
|
||||
auto operator[](K key) {
|
||||
auto ret = static_cast<T*>(m_dict->objectForKey(key));
|
||||
auto operator[](const Key& key) {
|
||||
auto ret = static_cast<ValuePtr>(m_dict->objectForKey(key));
|
||||
if (!ret) m_dict->setObject(cocos2d::CCNode::create(), key);
|
||||
|
||||
return CCDictEntry<K, T*>(key, m_dict);
|
||||
return CCDictEntry<Key, ValuePtr>(key, m_dict);
|
||||
}
|
||||
|
||||
size_t count(K key) {
|
||||
return m_dict->allKeys(key)->count();
|
||||
bool contains(const Key& key) {
|
||||
return m_dict->objectForKey(key) != nullptr;
|
||||
}
|
||||
|
||||
size_t count(const Key& key) {
|
||||
return this->contains(key) ? 1 : 0;
|
||||
}
|
||||
|
||||
cocos2d::CCDictionary* inner() {
|
||||
return m_dict;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
Binary file not shown.
|
@ -52,7 +52,7 @@ bool CCNode::hasAncestor(CCNode* ancestor) {
|
|||
|
||||
CCArray* Layout::getNodesToPosition(CCNode* on) const {
|
||||
auto arr = CCArray::create();
|
||||
for (auto child : CCArrayExt<CCNode>(on->getChildren())) {
|
||||
for (auto child : CCArrayExt<CCNode*>(on->getChildren())) {
|
||||
if (!m_ignoreInvisibleChildren || child->isVisible()) {
|
||||
arr->addObject(child);
|
||||
}
|
||||
|
@ -179,7 +179,7 @@ struct AxisLayout::Row : public CCObject {
|
|||
|
||||
void accountSpacers(Axis axis, float availableLength, float crossLength) {
|
||||
std::vector<SpacerNode*> spacers;
|
||||
for (auto& node : CCArrayExt<CCNode>(nodes)) {
|
||||
for (auto& node : CCArrayExt<CCNode*>(nodes)) {
|
||||
if (auto spacer = typeinfo_cast<SpacerNode*>(node)) {
|
||||
spacers.push_back(spacer);
|
||||
}
|
||||
|
@ -259,7 +259,7 @@ bool AxisLayout::shouldAutoScale(AxisLayoutOptions const* opts) const {
|
|||
float AxisLayout::minScaleForPrio(CCArray* nodes, int prio) const {
|
||||
float min = AXISLAYOUT_DEFAULT_MIN_SCALE;
|
||||
bool first = true;
|
||||
for (auto node : CCArrayExt<CCNode>(nodes)) {
|
||||
for (auto node : CCArrayExt<CCNode*>(nodes)) {
|
||||
auto scale = optsMinScale(axisOpts(node));
|
||||
if (first) {
|
||||
min = scale;
|
||||
|
@ -275,7 +275,7 @@ float AxisLayout::minScaleForPrio(CCArray* nodes, int prio) const {
|
|||
float AxisLayout::maxScaleForPrio(CCArray* nodes, int prio) const {
|
||||
float max = 1.f;
|
||||
bool first = true;
|
||||
for (auto node : CCArrayExt<CCNode>(nodes)) {
|
||||
for (auto node : CCArrayExt<CCNode*>(nodes)) {
|
||||
auto scale = optsMaxScale(axisOpts(node));
|
||||
if (first) {
|
||||
max = scale;
|
||||
|
@ -490,7 +490,7 @@ void AxisLayout::tryFitLayout(
|
|||
float crossSquishFactor = 0.f;
|
||||
|
||||
// make spacers have zero size so they don't affect spacing calculations
|
||||
for (auto& node : CCArrayExt<CCNode>(nodes)) {
|
||||
for (auto& node : CCArrayExt<CCNode*>(nodes)) {
|
||||
if (auto spacer = typeinfo_cast<SpacerNode*>(node)) {
|
||||
spacer->setContentSize(CCSizeZero);
|
||||
}
|
||||
|
@ -751,7 +751,7 @@ void AxisLayout::apply(CCNode* on) {
|
|||
bool doAutoScale = false;
|
||||
|
||||
bool first = true;
|
||||
for (auto node : CCArrayExt<CCNode>(nodes)) {
|
||||
for (auto node : CCArrayExt<CCNode*>(nodes)) {
|
||||
int prio = 0;
|
||||
if (auto opts = axisOpts(node)) {
|
||||
prio = opts->getScalePriority();
|
||||
|
|
|
@ -13,4 +13,4 @@ struct MyGameToolbox : Modify<MyGameToolbox, GameToolbox> {
|
|||
CCEGLView::get()->setScissorInPoints(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
|
@ -103,7 +103,7 @@ void CCNode::setID(std::string const& id) {
|
|||
}
|
||||
|
||||
CCNode* CCNode::getChildByID(std::string const& id) {
|
||||
for (auto child : CCArrayExt<CCNode>(m_pChildren)) {
|
||||
for (auto child : CCArrayExt<CCNode*>(m_pChildren)) {
|
||||
if (child->getID() == id) {
|
||||
return child;
|
||||
}
|
||||
|
@ -115,7 +115,7 @@ CCNode* CCNode::getChildByIDRecursive(std::string const& id) {
|
|||
if (auto child = this->getChildByID(id)) {
|
||||
return child;
|
||||
}
|
||||
for (auto child : CCArrayExt<CCNode>(m_pChildren)) {
|
||||
for (auto child : CCArrayExt<CCNode*>(m_pChildren)) {
|
||||
if ((child = child->getChildByIDRecursive(id))) {
|
||||
return child;
|
||||
}
|
||||
|
@ -131,7 +131,7 @@ void CCNode::removeChildByID(std::string const& id) {
|
|||
|
||||
void CCNode::setLayout(Layout* layout, bool apply, bool respectAnchor) {
|
||||
if (respectAnchor && this->isIgnoreAnchorPointForPosition()) {
|
||||
for (auto child : CCArrayExt<CCNode>(m_pChildren)) {
|
||||
for (auto child : CCArrayExt<CCNode*>(m_pChildren)) {
|
||||
child->setPosition(child->getPosition() + this->getScaledContentSize());
|
||||
}
|
||||
this->ignoreAnchorPointForPosition(false);
|
||||
|
|
|
@ -7,6 +7,7 @@ static constexpr int LOADER_VERSION_MAJOR = @PROJECT_VERSION_MAJOR@;
|
|||
static constexpr int LOADER_VERSION_MINOR = @PROJECT_VERSION_MINOR@;
|
||||
static constexpr int LOADER_VERSION_PATCH = @PROJECT_VERSION_PATCH@;
|
||||
static constexpr const char* LOADER_COMMIT_HASH = "@GEODE_COMMIT_HASH@";
|
||||
static constexpr const char* BINDINGS_COMMIT_HASH = "@GEODE_BINDINGS_COMMIT_HASH@";
|
||||
static constexpr geode::VersionInfo LOADER_VERSION = {
|
||||
@PROJECT_VERSION_MAJOR@,
|
||||
@PROJECT_VERSION_MINOR@,
|
||||
|
|
|
@ -20,6 +20,7 @@ std::string crashlog::getDateString(bool filesafe) {
|
|||
void crashlog::printGeodeInfo(std::stringstream& stream) {
|
||||
stream << "Loader Version: " << Loader::get()->getVersion().toString() << "\n"
|
||||
<< "Loader Commit: " << LOADER_COMMIT_HASH << "\n"
|
||||
<< "Bindings Commit: " << BINDINGS_COMMIT_HASH << "\n"
|
||||
<< "Installed mods: " << Loader::get()->getAllMods().size() << "\n"
|
||||
<< "Problems: " << Loader::get()->getProblems().size() << "\n";
|
||||
}
|
||||
|
|
|
@ -105,19 +105,19 @@ std::vector<std::string> Mod::getSettingKeys() const {
|
|||
return m_impl->getSettingKeys();
|
||||
}
|
||||
|
||||
bool Mod::hasSetting(std::string const& key) const {
|
||||
bool Mod::hasSetting(std::string_view const key) const {
|
||||
return m_impl->hasSetting(key);
|
||||
}
|
||||
|
||||
std::optional<Setting> Mod::getSettingDefinition(std::string const& key) const {
|
||||
std::optional<Setting> Mod::getSettingDefinition(std::string_view const key) const {
|
||||
return m_impl->getSettingDefinition(key);
|
||||
}
|
||||
|
||||
SettingValue* Mod::getSetting(std::string const& key) const {
|
||||
SettingValue* Mod::getSetting(std::string_view const key) const {
|
||||
return m_impl->getSetting(key);
|
||||
}
|
||||
|
||||
void Mod::registerCustomSetting(std::string const& key, std::unique_ptr<SettingValue> value) {
|
||||
void Mod::registerCustomSetting(std::string_view const key, std::unique_ptr<SettingValue> value) {
|
||||
return m_impl->registerCustomSetting(key, std::move(value));
|
||||
}
|
||||
|
||||
|
@ -172,7 +172,7 @@ ModRequestedAction Mod::getRequestedAction() const {
|
|||
return m_impl->getRequestedAction();
|
||||
}
|
||||
|
||||
bool Mod::depends(std::string const& id) const {
|
||||
bool Mod::depends(std::string_view const id) const {
|
||||
return m_impl->depends(id);
|
||||
}
|
||||
|
||||
|
@ -200,7 +200,7 @@ void Mod::setLoggingEnabled(bool enabled) {
|
|||
m_impl->setLoggingEnabled(enabled);
|
||||
}
|
||||
|
||||
bool Mod::hasSavedValue(std::string const& key) {
|
||||
bool Mod::hasSavedValue(std::string_view const key) {
|
||||
return this->getSaveContainer().contains(key);
|
||||
}
|
||||
|
||||
|
|
|
@ -258,13 +258,14 @@ void Mod::Impl::setupSettings() {
|
|||
}
|
||||
}
|
||||
|
||||
void Mod::Impl::registerCustomSetting(std::string const& key, std::unique_ptr<SettingValue> value) {
|
||||
if (!m_settings.count(key)) {
|
||||
void Mod::Impl::registerCustomSetting(std::string_view const key, std::unique_ptr<SettingValue> value) {
|
||||
auto keystr = std::string(key);
|
||||
if (!m_settings.count(keystr)) {
|
||||
// load data
|
||||
if (m_savedSettingsData.contains(key)) {
|
||||
value->load(m_savedSettingsData[key]);
|
||||
}
|
||||
m_settings.emplace(key, std::move(value));
|
||||
m_settings.emplace(keystr, std::move(value));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -280,7 +281,7 @@ std::vector<std::string> Mod::Impl::getSettingKeys() const {
|
|||
return keys;
|
||||
}
|
||||
|
||||
std::optional<Setting> Mod::Impl::getSettingDefinition(std::string const& key) const {
|
||||
std::optional<Setting> Mod::Impl::getSettingDefinition(std::string_view const key) const {
|
||||
for (auto& setting : m_metadata.getSettings()) {
|
||||
if (setting.first == key) {
|
||||
return setting.second;
|
||||
|
@ -289,14 +290,16 @@ std::optional<Setting> Mod::Impl::getSettingDefinition(std::string const& key) c
|
|||
return std::nullopt;
|
||||
}
|
||||
|
||||
SettingValue* Mod::Impl::getSetting(std::string const& key) const {
|
||||
if (m_settings.count(key)) {
|
||||
return m_settings.at(key).get();
|
||||
SettingValue* Mod::Impl::getSetting(std::string_view const key) const {
|
||||
auto keystr = std::string(key);
|
||||
|
||||
if (m_settings.count(keystr)) {
|
||||
return m_settings.at(keystr).get();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool Mod::Impl::hasSetting(std::string const& key) const {
|
||||
bool Mod::Impl::hasSetting(std::string_view const key) const {
|
||||
for (auto& setting : m_metadata.getSettings()) {
|
||||
if (setting.first == key) {
|
||||
return true;
|
||||
|
@ -449,7 +452,7 @@ bool Mod::Impl::hasUnresolvedIncompatibilities() const {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Mod::Impl::depends(std::string const& id) const {
|
||||
bool Mod::Impl::depends(std::string_view const id) const {
|
||||
return utils::ranges::contains(m_metadata.getDependencies(), [id](ModMetadata::Dependency const& t) {
|
||||
return t.id == id;
|
||||
});
|
||||
|
@ -585,13 +588,13 @@ Result<> Mod::Impl::unzipGeodeFile(ModMetadata metadata) {
|
|||
if (ec) {
|
||||
return Err("Unable to delete temp dir: " + ec.message());
|
||||
}
|
||||
|
||||
|
||||
(void)utils::file::createDirectoryAll(tempDir);
|
||||
auto res = file::writeString(datePath, modifiedHash);
|
||||
if (!res) {
|
||||
log::warn("Failed to write modified date of geode zip: {}", res.unwrapErr());
|
||||
}
|
||||
|
||||
|
||||
|
||||
GEODE_UNWRAP_INTO(auto unzip, file::Unzip::create(metadata.getPath()));
|
||||
if (!unzip.hasEntry(metadata.getBinaryName())) {
|
||||
|
|
|
@ -109,10 +109,10 @@ namespace geode {
|
|||
|
||||
bool hasSettings() const;
|
||||
std::vector<std::string> getSettingKeys() const;
|
||||
bool hasSetting(std::string const& key) const;
|
||||
std::optional<Setting> getSettingDefinition(std::string const& key) const;
|
||||
SettingValue* getSetting(std::string const& key) const;
|
||||
void registerCustomSetting(std::string const& key, std::unique_ptr<SettingValue> value);
|
||||
bool hasSetting(std::string_view const key) const;
|
||||
std::optional<Setting> getSettingDefinition(std::string_view const key) const;
|
||||
SettingValue* getSetting(std::string_view const key) const;
|
||||
void registerCustomSetting(std::string_view const key, std::unique_ptr<SettingValue> value);
|
||||
|
||||
std::vector<Hook*> getHooks() const;
|
||||
Result<Hook*> addHook(Hook* hook);
|
||||
|
@ -129,7 +129,7 @@ namespace geode {
|
|||
// 1.3.0 additions
|
||||
ModRequestedAction getRequestedAction() const;
|
||||
|
||||
bool depends(std::string const& id) const;
|
||||
bool depends(std::string_view const id) const;
|
||||
Result<> updateDependencies();
|
||||
bool hasUnresolvedDependencies() const;
|
||||
bool hasUnresolvedIncompatibilities() const;
|
||||
|
|
|
@ -44,20 +44,49 @@ CCPoint cocos::getMousePos() {
|
|||
return CCPoint(0, 0);
|
||||
}
|
||||
|
||||
namespace {
|
||||
void clearJNIException() {
|
||||
// this is a silly workaround to not crash when the method is not found.
|
||||
// cocos figured this out half a year later...
|
||||
auto vm = JniHelper::getJavaVM();
|
||||
|
||||
JNIEnv* env;
|
||||
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) == JNI_OK) {
|
||||
env->ExceptionClear();
|
||||
}
|
||||
}
|
||||
|
||||
// jni breaks over multithreading, so the value is stored to avoid more jni calls
|
||||
std::string s_savedBaseDir = "";
|
||||
|
||||
ghc::filesystem::path getBaseDir() {
|
||||
std::string path = "/storage/emulated/0/Android/data/com.geode.launcher/files";
|
||||
|
||||
if (!s_savedBaseDir.empty()) {
|
||||
return ghc::filesystem::path(s_savedBaseDir);
|
||||
}
|
||||
|
||||
JniMethodInfo t;
|
||||
if (JniHelper::getStaticMethodInfo(t, "com/geode/launcher/utils/GeodeUtils", "getBaseDirectory", "()Ljava/lang/String;")) {
|
||||
jstring str = reinterpret_cast<jstring>(t.env->CallStaticObjectMethod(t.classID, t.methodID));
|
||||
t.env->DeleteLocalRef(t.classID);
|
||||
path = JniHelper::jstring2string(str);
|
||||
t.env->DeleteLocalRef(str);
|
||||
} else {
|
||||
clearJNIException();
|
||||
}
|
||||
|
||||
s_savedBaseDir = path;
|
||||
return ghc::filesystem::path(path);
|
||||
}
|
||||
}
|
||||
|
||||
ghc::filesystem::path dirs::getGameDir() {
|
||||
return ghc::filesystem::path(
|
||||
"/storage/emulated/0/Android/data/com.geode.launcher/files/game"
|
||||
// "/data/user/0/com.geode.launcher/files/"
|
||||
/*CCFileUtils::sharedFileUtils()->getWritablePath().c_str()*/
|
||||
);
|
||||
return getBaseDir() / "game";
|
||||
}
|
||||
|
||||
ghc::filesystem::path dirs::getSaveDir() {
|
||||
return ghc::filesystem::path(
|
||||
"/storage/emulated/0/Android/data/com.geode.launcher/files/save"
|
||||
// "/data/user/0/com.geode.launcher/files/"
|
||||
/*CCFileUtils::sharedFileUtils()->getWritablePath().c_str()*/
|
||||
);
|
||||
return getBaseDir() / "save";
|
||||
}
|
||||
|
||||
ghc::filesystem::path dirs::getModRuntimeDir() {
|
||||
|
|
46
loader/src/platform/windows/VersionDetect.hpp
Normal file
46
loader/src/platform/windows/VersionDetect.hpp
Normal file
|
@ -0,0 +1,46 @@
|
|||
#pragma once
|
||||
|
||||
#include <unordered_map>
|
||||
#include <string_view>
|
||||
#include <Windows.h>
|
||||
|
||||
// Original by absolute
|
||||
// https://gist.github.com/absoIute/ebe5da42d118109a03632c9751d86e19
|
||||
|
||||
inline std::string_view detectGDVersion() {
|
||||
static const std::unordered_map<uint32_t, std::string_view> buildMap = {
|
||||
{ 1419173053, "1.900" },
|
||||
{ 1419880840, "1.910" },
|
||||
{ 1421745341, "1.920" },
|
||||
{ 1440638199, "2.000" },
|
||||
{ 1440643927, "2.001" },
|
||||
{ 1443053232, "2.010" },
|
||||
{ 1443077847, "2.011" },
|
||||
{ 1443077847, "2.020" },
|
||||
{ 1484612867, "2.100" },
|
||||
{ 1484626658, "2.101" },
|
||||
{ 1484737207, "2.102" },
|
||||
{ 1510526914, "2.110" },
|
||||
{ 1510538091, "2.111" },
|
||||
{ 1510619253, "2.112" },
|
||||
{ 1511220108, "2.113" },
|
||||
{ 1702921605, "2.200" },
|
||||
{ 1704582672, "2.201" },
|
||||
{ 1704601266, "2.202" },
|
||||
};
|
||||
|
||||
auto hMod = GetModuleHandleA(NULL);
|
||||
auto dosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(hMod);
|
||||
|
||||
if (dosHeader->e_magic == IMAGE_DOS_SIGNATURE) {
|
||||
auto ntHeader = reinterpret_cast<PIMAGE_NT_HEADERS>(reinterpret_cast<uintptr_t>(hMod) + dosHeader->e_lfanew);
|
||||
|
||||
if (ntHeader->Signature == IMAGE_NT_SIGNATURE) {
|
||||
auto timeStamp = ntHeader->FileHeader.TimeDateStamp;
|
||||
if (auto it = buildMap.find(timeStamp); it != buildMap.end())
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include "../load.hpp"
|
||||
#include <Windows.h>
|
||||
#include "VersionDetect.hpp"
|
||||
|
||||
#include "loader/LoaderImpl.hpp"
|
||||
using namespace geode::prelude;
|
||||
|
@ -41,8 +42,10 @@ int WINAPI gdMainHook(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmd
|
|||
return reinterpret_cast<decltype(&wWinMain)>(mainTrampolineAddr)(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
|
||||
}
|
||||
|
||||
bool loadGeode() {
|
||||
// TODO: add version check or something
|
||||
std::string loadGeode() {
|
||||
if (detectGDVersion() != GEODE_STR(GEODE_GD_VERSION)) {
|
||||
return "GD version mismatch, not loading geode.";
|
||||
}
|
||||
|
||||
auto process = GetCurrentProcess();
|
||||
|
||||
|
@ -52,7 +55,7 @@ bool loadGeode() {
|
|||
MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE
|
||||
);
|
||||
|
||||
static constexpr uintptr_t MAIN_OFFSET = 0x3ba7d0;
|
||||
static constexpr uintptr_t MAIN_OFFSET = 0x3bdfd0;
|
||||
auto patchAddr = geode::base::get() + MAIN_OFFSET;
|
||||
|
||||
constexpr size_t patchSize = 6;
|
||||
|
@ -86,10 +89,10 @@ bool loadGeode() {
|
|||
|
||||
DWORD oldProtect;
|
||||
if (!VirtualProtectEx(process, reinterpret_cast<void*>(patchAddr), patchSize, PAGE_EXECUTE_READWRITE, &oldProtect))
|
||||
return false;
|
||||
return "Geode could not hook the main function, not loading geode.";
|
||||
std::memcpy(reinterpret_cast<void*>(patchAddr), patchBytes, patchSize);
|
||||
VirtualProtectEx(process, reinterpret_cast<void*>(patchAddr), patchSize, oldProtect, &oldProtect);
|
||||
return true;
|
||||
return "";
|
||||
}
|
||||
|
||||
DWORD WINAPI upgradeThread(void*) {
|
||||
|
@ -156,9 +159,9 @@ BOOL WINAPI DllMain(HINSTANCE module, DWORD reason, LPVOID) {
|
|||
}
|
||||
else if (oldBootstrapperExists)
|
||||
CreateThread(nullptr, 0, upgradeThread, nullptr, 0, nullptr);
|
||||
else if (!loadGeode()) {
|
||||
earlyError("There was an unknown error hooking the GD main function.");
|
||||
return FALSE;
|
||||
else if (auto error = loadGeode(); !error.empty()) {
|
||||
earlyError(error);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
catch(...) {
|
||||
|
|
|
@ -75,8 +75,17 @@ std::string utils::clipboard::read() {
|
|||
}
|
||||
|
||||
bool utils::file::openFolder(ghc::filesystem::path const& path) {
|
||||
ShellExecuteA(NULL, "open", path.string().c_str(), NULL, NULL, SW_SHOWDEFAULT);
|
||||
return true;
|
||||
auto success = false;
|
||||
if (CoInitializeEx(nullptr, COINIT_MULTITHREADED) == S_OK) {
|
||||
if (auto id = ILCreateFromPathW(path.wstring().c_str())) {
|
||||
if (SHOpenFolderAndSelectItems(id, 0, nullptr, 0) == S_OK) {
|
||||
success = true;
|
||||
}
|
||||
ILFree(id);
|
||||
}
|
||||
CoUninitialize();
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
Result<ghc::filesystem::path> utils::file::pickFile(
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
#include "HookListLayer.hpp"
|
||||
|
||||
#include <Geode/binding/GJListLayer.hpp>
|
||||
|
||||
bool HookListLayer::init(Mod* mod) {
|
||||
if (!GJDropDownLayer::init("Hooks", 220.f)) return false;
|
||||
|
||||
auto winSize = CCDirector::sharedDirector()->getWinSize();
|
||||
auto hooks = CCArray::create();
|
||||
for (auto const& hook : mod->getHooks()) {
|
||||
hooks->addObject(new HookItem(hook));
|
||||
}
|
||||
m_listLayer->m_listView = HookListView::create(hooks, mod, 356.f, 220.f);
|
||||
m_listLayer->addChild(m_listLayer->m_listView);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
HookListLayer* HookListLayer::create(Mod* mod) {
|
||||
auto ret = new HookListLayer;
|
||||
if (ret && ret->init(mod)) {
|
||||
ret->autorelease();
|
||||
return ret;
|
||||
}
|
||||
CC_SAFE_DELETE(ret);
|
||||
return nullptr;
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "HookListView.hpp"
|
||||
|
||||
#include <Geode/binding/GJDropDownLayer.hpp>
|
||||
|
||||
class HookListLayer : public GJDropDownLayer {
|
||||
protected:
|
||||
bool init(Mod* mod);
|
||||
|
||||
public:
|
||||
static HookListLayer* create(Mod* mod);
|
||||
};
|
|
@ -1,135 +0,0 @@
|
|||
#include "HookListView.hpp"
|
||||
|
||||
#include <Geode/binding/StatsCell.hpp>
|
||||
#include <Geode/binding/TableView.hpp>
|
||||
#include <Geode/binding/FLAlertLayer.hpp>
|
||||
#include <Geode/binding/CCMenuItemToggler.hpp>
|
||||
#include <Geode/utils/casts.hpp>
|
||||
#include <Geode/loader/Mod.hpp>
|
||||
|
||||
HookCell::HookCell(char const* name, CCSize size) : TableViewCell(name, size.width, size.height) {}
|
||||
|
||||
void HookCell::draw() {
|
||||
reinterpret_cast<StatsCell*>(this)->StatsCell::draw();
|
||||
}
|
||||
|
||||
void HookCell::updateBGColor(int index) {
|
||||
if (index & 1) m_backgroundLayer->setColor(ccc3(0xc2, 0x72, 0x3e));
|
||||
else m_backgroundLayer->setColor(ccc3(0xa1, 0x58, 0x2c));
|
||||
m_backgroundLayer->setOpacity(0xff);
|
||||
}
|
||||
|
||||
void HookCell::onEnable(CCObject* pSender) {
|
||||
auto toggle = as<CCMenuItemToggler*>(pSender);
|
||||
if (!toggle->isToggled()) {
|
||||
auto res = m_mod->enableHook(m_hook);
|
||||
if (!res) {
|
||||
FLAlertLayer::create(
|
||||
nullptr, "Error Enabling Hook", std::string(res.unwrapErr()), "OK", nullptr, 280.f
|
||||
)
|
||||
->show();
|
||||
}
|
||||
}
|
||||
else {
|
||||
auto res = m_mod->disableHook(m_hook);
|
||||
if (!res) {
|
||||
FLAlertLayer::create(
|
||||
nullptr, "Error Disabling Hook", std::string(res.unwrapErr()), "OK", nullptr, 280.f
|
||||
)
|
||||
->show();
|
||||
}
|
||||
}
|
||||
toggle->toggle(!m_hook->isEnabled());
|
||||
}
|
||||
|
||||
void HookCell::loadFromHook(Hook* hook, Mod* Mod) {
|
||||
m_hook = hook;
|
||||
m_mod = Mod;
|
||||
|
||||
m_mainLayer->setVisible(true);
|
||||
m_backgroundLayer->setOpacity(255);
|
||||
|
||||
auto menu = CCMenu::create();
|
||||
menu->setPosition(m_width - m_height, m_height / 2);
|
||||
m_mainLayer->addChild(menu);
|
||||
|
||||
auto enableBtn =
|
||||
CCMenuItemToggler::createWithStandardSprites(this, menu_selector(HookCell::onEnable), .6f);
|
||||
enableBtn->setPosition(0, 0);
|
||||
enableBtn->toggle(hook->isEnabled());
|
||||
menu->addChild(enableBtn);
|
||||
|
||||
std::stringstream moduleName;
|
||||
|
||||
// #ifdef GEODE_IS_WINDOWS // add other platforms?
|
||||
// HMODULE module;
|
||||
// if (GetModuleHandleExA(
|
||||
// GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
|
||||
// GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
|
||||
// as<LPCSTR>(hook->getAddress()),
|
||||
// &module
|
||||
// )) {
|
||||
// addr -= as<uintptr_t>(module);
|
||||
// char name[MAX_PATH];
|
||||
// if (GetModuleFileNameA(
|
||||
// module, name, sizeof name
|
||||
// )) {
|
||||
// auto fileName = std::filesystem::path(name).stem();
|
||||
// moduleName << fileName.string() << " + ";
|
||||
// }
|
||||
// }
|
||||
// #endif
|
||||
if (hook->getDisplayName() != "") moduleName << hook->getDisplayName();
|
||||
else moduleName << "0x" << std::hex << hook->getAddress();
|
||||
auto label = CCLabelBMFont::create(moduleName.str().c_str(), "chatFont.fnt");
|
||||
label->setPosition(m_height / 2, m_height / 2);
|
||||
label->setScale(.7f);
|
||||
label->setAnchorPoint({ .0f, .5f });
|
||||
m_mainLayer->addChild(label);
|
||||
}
|
||||
|
||||
HookCell* HookCell::create(char const* key, CCSize size) {
|
||||
auto pRet = new HookCell(key, size);
|
||||
if (pRet) {
|
||||
return pRet;
|
||||
}
|
||||
CC_SAFE_DELETE(pRet);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void HookListView::setupList(float) {
|
||||
m_itemSeparation = 30.0f;
|
||||
|
||||
if (!m_entries->count()) return;
|
||||
|
||||
m_tableView->reloadData();
|
||||
|
||||
if (m_entries->count() == 1)
|
||||
m_tableView->moveToTopWithOffset(m_itemSeparation);
|
||||
|
||||
m_tableView->moveToTop();
|
||||
}
|
||||
|
||||
TableViewCell* HookListView::getListCell(char const* key) {
|
||||
return HookCell::create(key, CCSize { m_width, m_itemSeparation });
|
||||
}
|
||||
|
||||
void HookListView::loadCell(TableViewCell* cell, int index) {
|
||||
as<HookCell*>(cell)->loadFromHook(
|
||||
as<HookItem*>(m_entries->objectAtIndex(index))->m_hook, m_mod
|
||||
);
|
||||
as<HookCell*>(cell)->updateBGColor(index);
|
||||
}
|
||||
|
||||
HookListView* HookListView::create(CCArray* hooks, Mod* Mod, float width, float height) {
|
||||
auto pRet = new HookListView;
|
||||
if (pRet) {
|
||||
pRet->m_mod = Mod;
|
||||
if (pRet->init(hooks, kBoomListType_Hooks, width, height)) {
|
||||
pRet->autorelease();
|
||||
return pRet;
|
||||
}
|
||||
}
|
||||
CC_SAFE_DELETE(pRet);
|
||||
return nullptr;
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <Geode/binding/CustomListView.hpp>
|
||||
#include <Geode/binding/TableViewCell.hpp>
|
||||
|
||||
using namespace geode::prelude;
|
||||
|
||||
static constexpr const BoomListType kBoomListType_Hooks = static_cast<BoomListType>(0x358);
|
||||
|
||||
struct HookItem : public CCObject {
|
||||
Hook* m_hook;
|
||||
|
||||
HookItem(Hook* h) : m_hook(h) {
|
||||
this->autorelease();
|
||||
}
|
||||
};
|
||||
|
||||
class HookCell : public TableViewCell {
|
||||
protected:
|
||||
Mod* m_mod;
|
||||
Hook* m_hook;
|
||||
|
||||
HookCell(char const* name, CCSize size);
|
||||
|
||||
void draw() override;
|
||||
|
||||
void onEnable(CCObject*);
|
||||
|
||||
public:
|
||||
void updateBGColor(int index);
|
||||
void loadFromHook(Hook*, Mod*);
|
||||
|
||||
static HookCell* create(char const* key, CCSize size);
|
||||
};
|
||||
|
||||
class HookListView : public CustomListView {
|
||||
protected:
|
||||
Mod* m_mod;
|
||||
|
||||
void setupList(float) override;
|
||||
TableViewCell* getListCell(char const* key) override;
|
||||
void loadCell(TableViewCell* cell, int index) override;
|
||||
|
||||
public:
|
||||
static HookListView* create(CCArray* hooks, Mod* Mod, float width, float height);
|
||||
};
|
|
@ -1,45 +0,0 @@
|
|||
#include "HotReloadLayer.hpp"
|
||||
|
||||
bool HotReloadLayer::init(std::string const& name) {
|
||||
if (!CCLayer::init()) return false;
|
||||
|
||||
auto winSize = CCDirector::sharedDirector()->getWinSize();
|
||||
|
||||
auto bg = CCSprite::create("GJ_gradientBG.png");
|
||||
auto bgSize = bg->getTextureRect().size;
|
||||
|
||||
bg->setAnchorPoint({ 0.0f, 0.0f });
|
||||
bg->setScaleX((winSize.width + 10.0f) / bgSize.width);
|
||||
bg->setScaleY((winSize.height + 10.0f) / bgSize.height);
|
||||
bg->setPosition({ -5.0f, -5.0f });
|
||||
bg->setColor({ 0, 102, 255 });
|
||||
|
||||
this->addChild(bg);
|
||||
|
||||
std::string text = "Reloading " + name + "...";
|
||||
auto label = CCLabelBMFont::create(text.c_str(), "bigFont.fnt");
|
||||
label->setPosition(this->getContentSize() / 2);
|
||||
label->setZOrder(1);
|
||||
label->setScale(.5f);
|
||||
this->addChild(label);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
HotReloadLayer* HotReloadLayer::create(std::string const& name) {
|
||||
auto ret = new HotReloadLayer;
|
||||
if (ret && ret->init(name)) {
|
||||
ret->autorelease();
|
||||
return ret;
|
||||
}
|
||||
CC_SAFE_DELETE(ret);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
HotReloadLayer* HotReloadLayer::scene(std::string const& name) {
|
||||
auto scene = CCScene::create();
|
||||
auto layer = HotReloadLayer::create(name);
|
||||
scene->addChild(layer);
|
||||
CCDirector::sharedDirector()->replaceScene(scene);
|
||||
return layer;
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <cocos2d.h>
|
||||
|
||||
using namespace geode::prelude;
|
||||
|
||||
class HotReloadLayer : public CCLayer {
|
||||
protected:
|
||||
bool init(std::string const& name);
|
||||
|
||||
public:
|
||||
static HotReloadLayer* create(std::string const& name);
|
||||
static HotReloadLayer* scene(std::string const& name);
|
||||
};
|
|
@ -1,6 +1,5 @@
|
|||
#include "ModInfoPopup.hpp"
|
||||
|
||||
#include "../dev/HookListLayer.hpp"
|
||||
#include "../list/ModListLayer.hpp"
|
||||
#include "../settings/ModSettingsPopup.hpp"
|
||||
#include <Geode/loader/Dirs.hpp>
|
||||
|
@ -523,11 +522,17 @@ bool LocalModInfoPopup::init(Mod* mod, ModListLayer* list) {
|
|||
m_mainLayer->addChild(m_minorVersionLabel);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
auto* label = CCLabelBMFont::create(LOADER_COMMIT_HASH, "chatFont.fnt");
|
||||
}
|
||||
if (mod == Mod::get()) {
|
||||
// we're showing the internal geode mod :-)
|
||||
auto* label = CCLabelBMFont::create(
|
||||
fmt::format("Bindings: {}\nLoader: {}", BINDINGS_COMMIT_HASH, LOADER_COMMIT_HASH).c_str(),
|
||||
"chatFont.fnt"
|
||||
);
|
||||
label->setAlignment(kCCTextAlignmentRight);
|
||||
label->setAnchorPoint(ccp(1, 0));
|
||||
label->setScale(0.775f);
|
||||
label->setPosition(winSize.width - 1.f, 1.f);
|
||||
label->setScale(0.6f);
|
||||
label->setPosition(winSize.width - 3.f, 3.f);
|
||||
label->setOpacity(89);
|
||||
m_mainLayer->addChild(label);
|
||||
}
|
||||
|
|
|
@ -578,7 +578,7 @@ void ModListLayer::reloadList(bool keepScroll, std::optional<ModListQuery> const
|
|||
}
|
||||
|
||||
void ModListLayer::updateAllStates() {
|
||||
for (auto cell : CCArrayExt<GenericListCell>(
|
||||
for (auto cell : CCArrayExt<GenericListCell*>(
|
||||
m_list->m_listView->m_tableView->m_cellArray
|
||||
)) {
|
||||
static_cast<ModListCell*>(cell->getChildByID("mod-list-cell"))->updateState();
|
||||
|
|
|
@ -58,7 +58,7 @@ public:
|
|||
// so that's why based MDContentLayer expects itself
|
||||
// to have a CCMenu :-)
|
||||
if (m_content) {
|
||||
for (auto child : CCArrayExt<CCNode>(m_content->getChildren())) {
|
||||
for (auto child : CCArrayExt<CCNode*>(m_content->getChildren())) {
|
||||
auto y = this->getPositionY() + child->getPositionY();
|
||||
child->setVisible(
|
||||
!((m_content->getContentSize().height < y) ||
|
||||
|
|
|
@ -35,7 +35,7 @@ void SceneManager::forget(CCNode* node) {
|
|||
}
|
||||
|
||||
void SceneManager::willSwitchToScene(CCScene* scene) {
|
||||
for (auto node : CCArrayExt<CCNode>(m_persistedNodes)) {
|
||||
for (auto node : CCArrayExt<CCNode*>(m_persistedNodes)) {
|
||||
// no cleanup in order to keep actions running
|
||||
node->removeFromParentAndCleanup(false);
|
||||
scene->addChild(node);
|
||||
|
|
|
@ -18,7 +18,7 @@ void GenericContentLayer::setPosition(CCPoint const& pos) {
|
|||
// all be TableViewCells
|
||||
CCLayerColor::setPosition(pos);
|
||||
|
||||
for (auto child : CCArrayExt<CCNode>(m_pChildren)) {
|
||||
for (auto child : CCArrayExt<CCNode*>(m_pChildren)) {
|
||||
auto y = this->getPositionY() + child->getPositionY();
|
||||
child->setVisible(!((m_obContentSize.height < y) || (y < -child->getContentSize().height)));
|
||||
}
|
||||
|
|
|
@ -246,7 +246,7 @@ CCNode* TextRenderer::end(
|
|||
case TextAlignment::End: padY = std::max(m_size.height - renderedHeight, 0.f); break;
|
||||
}
|
||||
// adjust child positions
|
||||
for (auto child : CCArrayExt<CCNode>(m_target->getChildren())) {
|
||||
for (auto child : CCArrayExt<CCNode*>(m_target->getChildren())) {
|
||||
child->setPosition(
|
||||
child->getPositionX() + padX,
|
||||
child->getPositionY() + m_target->getContentSize().height - coverage.size.height -
|
||||
|
|
|
@ -303,7 +303,7 @@ CCRect geode::cocos::calculateNodeCoverage(std::vector<CCNode*> const& nodes) {
|
|||
|
||||
CCRect geode::cocos::calculateNodeCoverage(CCArray* nodes) {
|
||||
CCRect coverage;
|
||||
for (auto child : CCArrayExt<CCNode>(nodes)) {
|
||||
for (auto child : CCArrayExt<CCNode*>(nodes)) {
|
||||
auto pos = child->getPosition() - child->getScaledContentSize() * child->getAnchorPoint();
|
||||
auto csize = child->getPosition() +
|
||||
child->getScaledContentSize() * (CCPoint{1.f, 1.f} - child->getAnchorPoint());
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# if(NOT GEODE_DONT_BUILD_TEST_MODS)
|
||||
# add_subdirectory(dependency)
|
||||
# add_subdirectory(main)
|
||||
# endif()
|
||||
if(NOT GEODE_DONT_BUILD_TEST_MODS)
|
||||
add_subdirectory(dependency)
|
||||
add_subdirectory(main)
|
||||
endif()
|
||||
|
||||
add_subdirectory(members)
|
|
@ -1,6 +1,6 @@
|
|||
#include "Common.hpp"
|
||||
|
||||
#ifdef GEODE_IS_WINDOWS
|
||||
#if 0
|
||||
|
||||
using namespace cocos2d;
|
||||
|
||||
|
|
Loading…
Reference in a new issue