### Setup a New Geode Profile Source: https://github.com/geode-sdk/docs/blob/main/getting-started/geode-cli.md Initiate the setup process for a new Geode profile, which typically involves configuring a Geometry Dash installation for use with Geode. ```bash geode config setup ``` -------------------------------- ### Full Web Request Example with Progress Source: https://github.com/geode-sdk/docs/blob/main/tutorials/fetch.md A complete example demonstrating how to hook into MenuLayer::init, perform a GET request with progress logging, and log the response string. This showcases integrating web requests into the game's lifecycle. ```cpp #include #include #include using namespace geode::prelude; class $modify(MenuLayer) { struct Fields { TaskHolder m_listener; }; bool init() { if (!MenuLayer::init()) { return false; } auto req = web::WebRequest(); req.onProgress([](web::WebProgress const& p) { log::info("progress: {}", p.downloadProgress().value_or(0.f)); }); m_fields->m_listener.spawn( req.get("https://pastebin.com/raw/vNi1WHNF"), [](web::WebResponse res) { log::info("{}", res.string().unwrapOr("Uh oh!")); } ); return true; } }; ``` -------------------------------- ### Install Geode SDK Source: https://github.com/geode-sdk/docs/blob/main/getting-started/sdk.md Run this command to download and install the Geode SDK. It should also set the GEODE_SDK environment variable. ```bash geode sdk install ``` -------------------------------- ### Install Android Binaries Source: https://github.com/geode-sdk/docs/blob/main/getting-started/create-mod.md Before building for Android, install the necessary Geode binaries for the target architecture using the CLI. ```bash geode sdk install-binaries -p android64 # Or if you're using a 32 bit phone geode sdk install-binaries -p android32 ``` -------------------------------- ### Install Geode CLI with Scoop (Windows) Source: https://github.com/geode-sdk/docs/blob/main/getting-started/geode-cli.md Use Scoop to install the Geode SDK CLI on Windows. This is a convenient method for managing the CLI installation. ```bash scoop bucket add extras scoop install geode-sdk-cli ``` -------------------------------- ### Linux Geode SDK Environment Setup Source: https://github.com/geode-sdk/docs/blob/main/getting-started/ide-setup.md This script sets up environment variables for Geode SDK development on Linux. Ensure paths match your installation if not using the default `geode sdk install-linux`. ```bash export GEODE_SDK=$HOME/Documents/Geode export SPLAT_DIR=$HOME/.local/share/Geode/cross-tools/splat export CMAKE_TOOLCHAIN_FILE=$HOME/.local/share/Geode/cross-tools/clang-msvc-sdk/clang-msvc.cmake export HOST_ARCH=x86_64 ``` -------------------------------- ### Install Prebuilt Geode Binaries Source: https://github.com/geode-sdk/docs/blob/main/getting-started/sdk.md Use this command to install prebuilt binaries for Geode, which is an alternative to building from source for mod development. ```bash geode sdk install-binaries ``` -------------------------------- ### Install Geode CLI with winget (Windows) Source: https://github.com/geode-sdk/docs/blob/main/getting-started/geode-cli.md Install the Geode CLI using the Windows Package Manager (winget). ```bash winget install GeodeSDK.GeodeCLI ``` -------------------------------- ### Install Clang, LLD, and LLVM on Fedora Source: https://github.com/geode-sdk/docs/blob/main/getting-started/cpp-stuff.md Installs the Clang compiler, LLD linker, and LLVM toolchain on Fedora. This is part of the setup for cross-compiling Windows Geode mods. ```bash dnf install clang lld llvm ``` -------------------------------- ### Install LLVM and Ninja on Windows using Scoop Source: https://github.com/geode-sdk/docs/blob/main/getting-started/cpp-stuff.md Installs the LLVM compiler and Ninja build system on Windows using the Scoop package manager. This is a recommended way to set up the necessary tools. ```bash scoop install llvm ninja ``` -------------------------------- ### Install Event Listener with Member Function Callback Source: https://github.com/geode-sdk/docs/blob/main/tutorials/events.md Install a custom event listener by defining it as a class member. The listener is automatically managed with the object's lifecycle. This example uses a member function `onDrop` as the callback. ```cpp // DragDropNode.hpp #include // CCNode #include // EventListener #include "DragDropOnNodeFilter.hpp" // Our filter class DragDropNode : public CCNode { protected: EventListener m_listener = { this, &DragDropNode::onDrop, // We defined a constructor with some arguments, so we have to construct our filter now DragDropOnNodeFilter(this, { ".gmd", ".gmd2", ".lvl" }) }; ListenerResult onDrop(std::vector const& files) { // Handle dropped files return ListenerResult::Propagate; } }; ``` -------------------------------- ### support.md Example Source: https://github.com/geode-sdk/docs/blob/main/mods/md-files.md This is an example of a support.md file, which provides information on how users can support the mod developer. It can include links to donation platforms or social media. ```md # Thank You for using Rattledasher 5000! If you like this mod and would like to support me, I have an [OnlyFans](https://globed.dev/soggy/)! You can see me rattle my dashes like a pro if you know what I mean ;) ``` -------------------------------- ### Basic C++ Hello World Source: https://github.com/geode-sdk/docs/blob/main/handbook/chap0.md A standard C++ program to print 'Hi mom!' to the console. This is a fundamental example often used to verify compiler setup. ```cpp #include int main() { std::cout << "Hi mom!\n"; } ``` -------------------------------- ### Install Linux Geode SDK tools using Geode CLI Source: https://github.com/geode-sdk/docs/blob/main/getting-started/cpp-stuff.md Installs all necessary tools for cross-compiling Windows Geode mods from Linux using the Geode CLI. This command simplifies the setup process. ```bash geode sdk install-linux ``` -------------------------------- ### about.md Example Source: https://github.com/geode-sdk/docs/blob/main/mods/md-files.md This is an example of an about.md file, which provides a free-form description for the mod. It supports a subset of Markdown features and is intended for end-users. ```md # My Awesome Mod This is my awesome mod, that does **all** the awesome stuff! If you like this mod, please check [my other mod](mod:my.other-mod)! ## Credits [Join my Discord](https://discord.gg/K9Kuh3hzTC)! Thanks to [Heinz Baked Beans](https://www.youtube.com/watch?v=-LVPjtLYia4) for helping with the mod! ``` -------------------------------- ### Install Geode CLI with Brew (macOS) Source: https://github.com/geode-sdk/docs/blob/main/getting-started/geode-cli.md Install the Geode CLI on macOS using the Homebrew package manager. ```bash brew install geode-sdk/geode/geode-cli ``` -------------------------------- ### Verify Geode CLI Installation Source: https://github.com/geode-sdk/docs/blob/main/getting-started/geode-cli.md After installation, verify that the Geode CLI is accessible by checking its version. This command should work on all platforms once the CLI is correctly installed and in the system's PATH. ```bash geode --version ``` -------------------------------- ### Title Setting Example Source: https://github.com/geode-sdk/docs/blob/main/mods/settings.md A cosmetic setting used to group other settings. It only supports 'name' and 'description' keys. ```json { "type": "title", "name": "Groovy Settings", "description": "These settings control how groovy you are" } ``` -------------------------------- ### changelog.md Example Source: https://github.com/geode-sdk/docs/blob/main/mods/md-files.md This is an example of a changelog.md file, used by Geode to display release notes for a mod. It typically lists versions and changes made in each release. ```md # v1.1.0 * Removed Herobrine # v1.0.1 * Fixed bugs # v1.0.0 * Initial release ``` -------------------------------- ### Mod Incompatibilities Example Source: https://github.com/geode-sdk/docs/blob/main/mods/configuring.md The 'incompatibilities' key lists mods that your mod cannot run alongside. This example shows a simple version-based incompatibility. ```json "incompatibilities": { // Or with the long form { "breaking": true, "version": "1.0.0" } "alphalaneous.improved_group_view": "1.0.0" } ``` -------------------------------- ### Build Mod with Ninja Source: https://github.com/geode-sdk/docs/blob/main/getting-started/create-mod.md If you have Clang and Ninja installed, this command can be used for building. It may offer performance improvements. ```bash # If you installed Clang and Ninja earlier, this is required instead # If this does not work, update your Geode CLI or use CMake directly geode build --ninja ``` -------------------------------- ### Create a New Mod Project Source: https://github.com/geode-sdk/docs/blob/main/getting-started/create-mod.md Run this command in your terminal to start a new mod project. Follow the prompts to configure your mod. ```bash geode new ``` -------------------------------- ### Install Event Listener with Lambda Callback Source: https://github.com/geode-sdk/docs/blob/main/tutorials/events.md Install a custom event listener using a lambda function as the callback. This is useful when a member function is not suitable, such as when hooking existing classes or when the listener needs to be defined inline. ```cpp EventListener m_listener = { [](std::vector const& files) { // Handle dropped files... return ListenerResult::Propagate; }, DragDropOnNodeFilter(this, { ".gmd", ".gmd2", ".lvl" }) }; ``` -------------------------------- ### Initialize MenuLayer and Get Screen Size Source: https://github.com/geode-sdk/docs/blob/main/handbook/vol1/chap1_7.md This snippet shows how to initialize a custom MenuLayer and retrieve the screen's dimensions using `getWinSize` from CCDirector. This is a prerequisite for positioning elements. ```cpp #include using namespace geode::prelude; class $modify(MenuLayer) { bool init() { if (!MenuLayer::init()) return false; auto winSize = CCDirector::get()->getWinSize(); auto label = CCLabelBMFont::create("Hello, World!", "bigFont.fnt"); this->addChild(label); return true; } }; ``` -------------------------------- ### Integer Setting Example Source: https://github.com/geode-sdk/docs/blob/main/mods/settings.md An integer setting with configurable controls like arrows, sliders, and input fields. Supports min/max values and step increments. ```json { "type": "int", "name": "Groovy Level", "description": "How groovy your grooving is", "default": 5, "min": 0, "max": 10, "control": { "arrows": true, "arrow-step": 1, "big-arrows": false, "big-arrow-step": 5, "slider": true, "slider-step": 1, "input": false } } ``` -------------------------------- ### Install Clang, LLD, and LLVM on Arch-based systems Source: https://github.com/geode-sdk/docs/blob/main/getting-started/cpp-stuff.md Installs the Clang compiler, LLD linker, and LLVM toolchain on Arch-based Linux distributions. This is required for cross-compiling Geode mods. ```bash pacman -S clang lld llvm ``` -------------------------------- ### Boolean Setting Example Source: https://github.com/geode-sdk/docs/blob/main/mods/settings.md A simple toggle setting. Use this for enabling or disabling features. ```json { "type": "bool", "name": "Enable Groovy Mode", "description": "Bring some real action to this lame ass party", "default": true } ``` -------------------------------- ### Pre and Post Priority Differentiation Example Source: https://github.com/geode-sdk/docs/blob/main/tutorials/hookpriority.md Illustrates the difference between pre- and post- execution priorities. Pre- priorities execute code before the original function, while Post- priorities execute after. This example shows various hook execution orders. ```cpp void functionEarlyPre() { log::info("statement 1"); function(); } ``` ```cpp void functionLatePre() { log::info("statement 3"); function(); } ``` ```cpp void functionNormal() { log::info("statement 2"); function(); log::info("statement 5"); } ``` ```cpp void functionEarlyPost() { function(); log::info("statement 4"); } ``` ```cpp void functionLatePost() { function(); log::info("statement 6"); } ``` -------------------------------- ### Install LLVM on macOS using Homebrew Source: https://github.com/geode-sdk/docs/blob/main/getting-started/cpp-stuff.md Installs the LLVM compiler on macOS using the Homebrew package manager. This is a prerequisite for C++ development on macOS. ```bash brew install llvm ``` -------------------------------- ### Show Popup on Game Launch Source: https://github.com/geode-sdk/docs/blob/main/tutorials/popup.md Displays a popup when the game is loaded using the $on_game(Loaded) event. This simplifies showing popups on game start without manual tracking. ```cpp $on_game(Loaded) { auto alert = FLAlertLayer::create( "Title", "Hi mom!", "OK" ); alert->show(); } ``` -------------------------------- ### Original Function Example Source: https://github.com/geode-sdk/docs/blob/main/handbook/vol1/chap1_2.md A simple C++ function that adds two integers. This serves as the base for demonstrating hooking. ```cpp int addTwo(int a, int b) { return a + b; } ``` -------------------------------- ### API Mod Header Example Source: https://github.com/geode-sdk/docs/blob/main/mods/dependencies.md Example of an API mod's distributed header file. Functions intended for export must be declared inline and return a `geode::Result`. The `MY_MOD_ID` must be manually declared. ```cpp #pragma once #include #undef MY_MOD_ID // You must **manually** declare the mod id, as macros like GEODE_MOD_ID will not // behave correctly to other mods using your api. #define MY_MOD_ID "dev.my-api" namespace api { // Important: The function must be declared inline, and return a geode::Result, // as it can fail if the api is not available. inline geode::Result addNumbers(int a, int b) GEODE_EVENT_EXPORT(&addNumbers, (a, b)); // Alternatively, use the `_NORES` variant of the macro, which will return a default value // if the api isn't available. Ex: this will return 0 if the mod is unavailable inline int factorial(int x) GEODE_EVENT_EXPORT_NORES(&factorial, (x)); // It also works with void: inline void doSomething() GEODE_EVENT_EXPORT_NORES(&doSomething, ()); } ``` -------------------------------- ### Modifying MenuLayer with $modify Source: https://github.com/geode-sdk/docs/blob/main/handbook/vol1/chap1_6.md An example demonstrating how to use $modify to hook into the game's MenuLayer. Ensure the relevant header is included before use. ```cpp #include class $modify(MenuLayer) { // Overwrite functions, etc. }; ``` -------------------------------- ### Registering a Virtual Function for Modification Source: https://github.com/geode-sdk/docs/blob/main/tutorials/modify.md This example shows how to register a virtual function for modification using `registerVirtual`. While the implementation of `copyWithZone` is noted as a placeholder, this demonstrates the syntax for preparing virtual functions to be overridden or extended in derived classes. ```cpp class $modify(CopyPlayerObject, PlayerObject) { static void onModify(auto& self) { self.registerVirtual(&CopyPlayerObject::copyWithZone); } CCObject* copyWithZone(CCZone* zone) { log::info("This function is a meme really"); } }; ``` -------------------------------- ### Correct Function Definition Source: https://github.com/geode-sdk/docs/blob/main/source/styling.md Function definitions should start on the same line as the return type and parameters. The opening brace should follow on the same line. ```cpp // Correct CCObject* copyWithMeme(CCMeme* meme) { return nullptr; // funny meme if i do say so myself } ``` ```cpp // Wrong CCObject* copyWithMeme(CCMeme* meme) { return nullptr; } ``` -------------------------------- ### Verify GEODE_SDK Environment Variable Source: https://github.com/geode-sdk/docs/blob/main/getting-started/sdk.md After installing the SDK and restarting your terminal, use these commands to verify that the GEODE_SDK environment variable has been set correctly. ```bash # On Windows CMD echo %GEODE_SDK% ``` ```powershell # On Windows PowerShell echo $env:GEODE_SDK ``` ```bash # Elsewhere echo $GEODE_SDK ``` -------------------------------- ### Button with Tagged Callbacks Source: https://github.com/geode-sdk/docs/blob/main/tutorials/buttons.md Demonstrates passing additional parameters to button callbacks using tags. This example adds a decrement button and uses the tag to determine the action. ```cpp class MyLayer : public CCLayer { protected: // Class member that stores how many times // the button has been clicked size_t m_clicked = 0; bool init() { if (!CCLayer::init()) return false; auto menu = CCMenu::create(); auto btn = CCMenuItemSpriteExtra::create( ButtonSprite::create("Click me!"), this, menu_selector(MyLayer::onClick) ); btn->setPosition(100.f, 100.f); btn->setTag(1); menu->addChild(btn); auto btn2 = CCMenuItemSpriteExtra::create( ButtonSprite::create("Decrement"), this, menu_selector(MyLayer::onClick) ); btn2->setPosition(100.f, 60.f); btn2->setTag(-1); menu->addChild(btn2); this->addChild(menu); return true; } void onClick(CCObject* sender) { // Increment or decrement click count m_clicked += sender->getTag(); auto btn = static_cast(sender); // getNormalImage returns the sprite of the button auto spr = static_cast(btn->getNormalImage()); spr->setString(CCString::createWithFormat( "Clicked %d times", m_clicked )->getCString()); } }; ``` -------------------------------- ### Install Geode Binaries for iOS Source: https://github.com/geode-sdk/docs/blob/main/misc/ios.md Use the Geode CLI to download the necessary binaries for iOS development. Ensure your SDK version is 4.4.0 or higher. ```bash geode sdk install-binaries --platform ios ``` -------------------------------- ### Use Geode's pathToString instead of std::filesystem::path::string() Source: https://github.com/geode-sdk/docs/blob/main/mods/guidelines-tips.md Avoid potential crashes on certain setups by using Geode's `pathToString` for converting `std::filesystem::path` to string. ```cpp std::string pathStr = geode::utils::string::pathToString(myPath); ``` -------------------------------- ### Create and Configure a WebRequest Source: https://github.com/geode-sdk/docs/blob/main/tutorials/fetch.md Instantiate a WebRequest object and set various parameters like query parameters, User-Agent, request body, headers, and timeout. Use this to prepare your HTTP request. ```cpp #include web::WebRequest req = web::WebRequest(); // Let's add some query params req.param("one", "two"); req.param("three", "four"); // Maybe set our UserAgent? req.userAgent("Geode Web Request!"); // For POST / PUT requests, we should probably send a body. Choose whichever suits your needs // Byte vector (std::vector) req.body({ 0x23, 0x24, 0x25 }); // Strings req.bodyString("Hello, server!"); // JSON (uses any matjson::Value) // Note that you should probably have some actual data in your json auto myjson = matjson::Value(); req.bodyJSON(myjson); // Let's set some headers, shall we? req.header("Content-Type", "application/json"); // Set a timeout for the request, in seconds req.timeout(std::chrono::seconds(30)); ``` -------------------------------- ### Basic CCArray Member Initialization Source: https://github.com/geode-sdk/docs/blob/main/tutorials/memory.md This snippet shows the basic initialization of a `CCArray` as a member of a `CCNode` subclass. It demonstrates the initial setup without explicit memory management, which can lead to crashes. ```cpp class MyNode : public CCNode { protected: CCArray* m_array; bool init() { if (!CCNode::init()) return false; m_array = CCArray::create(); return true; } public: CCObject* getFirst() const { return m_array->firstObject(); } }; ``` -------------------------------- ### Running a Task with Progress and Cancellation Source: https://github.com/geode-sdk/docs/blob/main/tutorials/tasks.md This example demonstrates how to wrap a calculation within a Task using `Task::run`. It includes logic to handle cancellation requests and post progress updates. A descriptive name is provided for debugging purposes. ```cpp SumTask startCalculation() { return SumTask::run([](auto progress, auto hasBeenCancelled) -> SumTask::Result { uint64_t sum = 0u; for (uint64_t i = 1U; i <= 10'000'000U; i++) { // Check for cancellation and early return if the Task has been cancelled. if (hasBeenCancelled()) { return SumTask::Cancel(); } // Do our summing sum += i; // Post the progress progress(static_cast(std::ceil(i / 10'000'000U * 100))) } return sum; }, "My epic task that sums up numbers for some reason"); } ``` -------------------------------- ### Hooking a Class Method Manually Source: https://github.com/geode-sdk/docs/blob/main/tutorials/manualhooks.md This snippet demonstrates how to manually hook a class method, `MenuLayer::onNewgrounds`, using `Mod::hook`. It includes the detour function and the necessary setup within the `$on_mod(Loaded)` block. Note that this specific example is for illustrative purposes and should not be used in practice as `$modify` is sufficient. ```cpp void MenuLayer_onNewgrounds(MenuLayer* self, CCObject* sender) { log::info("Hook reached!"); // You can call the original by calling it - in this case, since the // original is in bindings, you can just call it the same way as you // would with $modify // TODO: How to call original manually self->onNewgrounds(sender); log::info("After original!"); } $on_mod(Loaded) { Mod::get()->hook( reinterpret_cast(geode::base::get() + 0x191E90), // address &MenuLayer_onNewgrounds, // detour "MenuLayer::onNewgrounds", // display name, shows up on the console tulip::hook::TulipConvention::Thiscall // calling convention ); } ``` -------------------------------- ### Managing Task Lifecycle with TaskHandle Source: https://github.com/geode-sdk/docs/blob/main/tutorials/async.md Demonstrates how to spawn a task, retrieve its handle, and then await its result, block until completion, or cancel it. Use `blockOn()` with caution as it can cause resource starvation within a runtime. ```cpp auto handle = async::spawn([] -> arc::Future { // yield() is like a tiny sleep co_await arc::yield(); co_return 42; }); // if we are inside a coroutine, we can await the task and get the output int value = co_await handle; // if we are NOT inside a coroutine, we can block until it's done // *never* use this when inside a runtime, because that causes resource starvation int value = handle.blockOn(); // if we don't care about the task, we can cancel it, which will cleanup all resources owned by it handle.abort(); ``` -------------------------------- ### Launching a global file picker with async/await Source: https://github.com/geode-sdk/docs/blob/main/tutorials/migrate-v5.md Replaces the v4 file picker method using .listen() with the new asynchronous system using async::spawn and coroutines. This is the recommended way to handle asynchronous file operations. ```cpp file::pick(...).listen([](Result* path) { if (path && path->isOk()) { auto path = path->unwrap(); } }); ``` ```cpp #include async::spawn( file::pick(...), [](Result> result) { // note that this is not a pointer anymore! if (result.isOk()) { auto opt = result.unwrap(); if (opt) { auto path = opt.value(); } else { // User cancelled the dialog } } } ); ``` -------------------------------- ### Create a Simple Info Popup Source: https://github.com/geode-sdk/docs/blob/main/tutorials/popup.md Use FLAlertLayer::create for basic information popups. This is the recommended method for displaying simple messages to the user. ```cpp FLAlertLayer::create( "Title", // title "Hi mom!", // content "OK" // button )->show(); ``` -------------------------------- ### Get Function Addresses with addresser Source: https://github.com/geode-sdk/docs/blob/main/tutorials/utils.md Use `addresser::getNonVirtual` to get the address of a non-virtual function and `addresser::getVirtual` for virtual functions. ```cpp // Get the address of a non-virtual function auto address1 = addresser::getNonVirtual(&MenuLayer::onMoreGames); // Get the address of a virtual function auto address2 = addresser::getVirtual(&MenuLayer::init); ``` -------------------------------- ### Build Geode Docs with Flash Source: https://github.com/geode-sdk/docs/blob/main/README.md Use the Flash command-line tool to build the Geode documentation. Specify the path to your Geode source code using -i and the desired output directory using -o. The --overwrite flag will replace existing files in the output directory. ```bash flash -i -o --overwrite ``` -------------------------------- ### Add a Geode Profile Source: https://github.com/geode-sdk/docs/blob/main/getting-started/geode-cli.md Register a Geometry Dash installation with Geode as a profile. This is necessary for managing mods and builds across different installations. ```bash geode profile add ``` -------------------------------- ### Setting Hook Priority Source: https://github.com/geode-sdk/docs/blob/main/tutorials/modify.md This example shows how to set a specific priority for a hook, allowing your code to run before or after other hooks. Use `Priority::Early` to ensure your hook executes before others. This is useful when your mod's execution order is critical. ```cpp class $modify(GJGarageLayer) { static void onModify(auto& self) { self.setHookPriorityPost("GJGarageLayer::init", Priority::Early); } bool init() { if (!GJGarageLayer::init()) return false; NodeIDs::get()->provide(this); return true; } }; ``` -------------------------------- ### Install Clang and LLD on Ubuntu Source: https://github.com/geode-sdk/docs/blob/main/getting-started/cpp-stuff.md Installs specific versions of Clang and LLD for cross-compiling Windows Geode mods on Ubuntu. Ensure you have at least CMake 3.29. ```bash apt install clang-19 clang-tools-19 lld-19 ``` -------------------------------- ### Clone Geode and Docs Repositories Source: https://github.com/geode-sdk/docs/blob/main/README.md Clone the Geode repository and then clone the docs repository inside the Geode root directory to set up the correct folder structure for building. ```bash git clone https://github.com/geode-sdk/geode cd geode git clone https://github.com/geode-sdk/docs ``` -------------------------------- ### Hello, World! Mod Implementation Source: https://github.com/geode-sdk/docs/blob/main/handbook/vol1/chap1_7.md This C++ code implements a simple 'Hello, World!' mod for Geometry Dash. It hooks into the MenuLayer's initialization to add a 'Hello, World!' text label to the main menu. Ensure you have the Geode SDK included. ```cpp #include using namespace geode::prelude; class $modify(MenuLayer) { bool init() { if (!MenuLayer::init()) return false; auto winSize = CCDirector::get()->getWinSize(); auto label = CCLabelBMFont::create("Hello, World!", "bigFont.fnt"); label->setPosition(winSize / 2); this->addChild(label); return true; } }; ``` -------------------------------- ### Thread Naming with geode::utils::thread Source: https://github.com/geode-sdk/docs/blob/main/tutorials/utils.md Allows getting and setting the name of the current thread. ```cpp auto name = thread::getName(); thread::setName("MyThread"); ``` -------------------------------- ### Create a Confirmation Popup with Callback Source: https://github.com/geode-sdk/docs/blob/main/tutorials/popup.md Use geode::createQuickPopup for confirmation dialogs. It simplifies handling button clicks with a std::function callback, avoiding FLAlertLayerProtocol boilerplate. ```cpp geode::createQuickPopup( "Title", // title "Say hi to mom?", // content "Nah", "Yeah", // buttons [](auto, bool btn2) { if (btn2) { // say hi to mom } } ); ``` -------------------------------- ### Correct Multi-Line Comments Source: https://github.com/geode-sdk/docs/blob/main/source/styling.md For multi-line comments, the content should start on a new line with proper indentation. ```cpp /* This is quite correct. Isn't it? */ ``` -------------------------------- ### Basic Hooking Implementation Source: https://github.com/geode-sdk/docs/blob/main/handbook/vol1/chap1_2.md Illustrates the fundamental concept of hooking by introducing a detour function that logs a message before calling the original function. ```cpp int addTwo(int a, int b) { addTwoHook(a, b); return a + b; } int addTwoHook(int a, int b) { std::cout << "addTwo called!\n"; } ``` -------------------------------- ### Incorrect Other Macro Source: https://github.com/geode-sdk/docs/blob/main/source/styling.md Other macros should not be in mixed case or lack the 'GEODE_' prefix. These examples show incorrect formats. ```cpp // Wrong #define DEFINEFUNCLOL(...) #define OrThisOne(...) ``` -------------------------------- ### Build Mod for Current Platform Source: https://github.com/geode-sdk/docs/blob/main/getting-started/create-mod.md Use this command to configure and build your mod for the current operating system. It's the standard build command. ```bash # Configures & builds for the current platform geode build ``` -------------------------------- ### Create and Load LazySprite Source: https://github.com/geode-sdk/docs/blob/main/tutorials/image-loading.md Demonstrates creating a LazySprite, optionally disabling the loading circle, and setting a callback for load completion or failure. It shows how to load images from a URL, file, or binary data. ```cpp #include using namespace geode::prelude; // this will be the initial size of the node (and the loading circle) CCSize nodeSize{64.f, 64.f}; auto spr1 = LazySprite::create(nodeSize); // or, if you want to disable the loading circle auto spr1 = LazySprite::create(nodeSize, false); // if you want to know when the image finished loading, you can assign a callback // do this **before** calling one of the next functions, because if the image is cached, // the callback will be called instantly, potentially before you assign it. spr1->setLoadCallback([spr1](Result<> res) { if (res) { log::info("Sprite loaded successfully!"); } else { log::error("Sprite failed to load, setting fallback: {}", res.unwrapErr()); spr1->initWithSpriteFrameName("globed-logo.png"_spr); } }); // load the image from a URL spr1->loadFromUrl("https://globed.dev/logo.png"); // or, load from a file spr1->loadFromFile(Mod::get()->getSaveDir() / "file.png"); // or, load from binary data std::vector pngBytes = {0x1, 0x2, 0x3}; spr1->loadFromData(std::move(pngBytes)); // using cocos methods also works, but does not have any performance benefits: spr1->initWithFile("my-file.png"); spr1->initWithSpriteFrameName("my-texture.png"); // note: you MUST either add the sprite as a child or store it in a Ref<> // if the sprite node gets deleted then it will stop loading and will never call your callback someMenu->addChild(spr1); ``` -------------------------------- ### Get Integer Setting Value Source: https://github.com/geode-sdk/docs/blob/main/mods/settings.md Retrieves the current integer value of a setting. Use `int64_t` for the template type. ```cpp auto value = Mod::get()->getSettingValue("int-setting-example"); ``` -------------------------------- ### Get Boolean Setting Value Source: https://github.com/geode-sdk/docs/blob/main/mods/settings.md Retrieves the current boolean value of a setting. Ensure the setting key matches. ```cpp auto value = Mod::get()->getSettingValue("bool-setting-example"); ``` -------------------------------- ### Advanced fmtlib Formatting in Logs Source: https://github.com/geode-sdk/docs/blob/main/tutorials/logging.md Demonstrates advanced formatting capabilities using fmtlib syntax, including right-alignment, precision, and joining vector elements. Requires `using namespace geode::prelude;` or `geode::` prefix. ```cpp geode::log::debug("Hello {:>10.3f} world, [{}]", 12.4f, fmt::join(someVec, ", ")); ``` -------------------------------- ### Using WeakRef in a Map Source: https://github.com/geode-sdk/docs/blob/main/tutorials/memory.md This example demonstrates the use of `WeakRef` in a map, which does not affect the reference count of the pointed-to object. ```cpp static std::unordered_map, SomeData> REGISTERED_NODES {}; void addDataToNode(CCNode* node, SomeData const& data) { REGISTERED_NODES.insert({ node, data }); } void doSomethingWithNodes() { for (auto& [node, data] : REGISTERED_NODES) { // ... } } ``` -------------------------------- ### Incorrect Syntactical Macro Source: https://github.com/geode-sdk/docs/blob/main/source/styling.md Syntactical macros should not contain multiple words or mixed casing. This example shows an incorrect format. ```cpp // Wrong #define $modifyThisDamnedClass(...) // lol ``` -------------------------------- ### Refactoring geode::Popup initialization Source: https://github.com/geode-sdk/docs/blob/main/tutorials/migrate-v5.md Demonstrates the refactoring of geode::Popup initialization from a templated class to a non-templated one with arguments passed to Popup::init. Use this when updating older Geode projects. ```cpp class MyPopup : public Popup { public: static MyPopup* create(int value) { auto popup = new MyPopup; if (popup->initAnchored(320.f, 160.f, value)) { popup->autorelease(); return popup; } delete popup; return nullptr; } protected: bool setup(int value) override { auto node = CCLabelBMFont::create("Hi", "bigFont.fnt"); this->addChild(node); return true; } }; ``` ```cpp class MyPopup : public Popup { public: static MyPopup* create(int value) { auto popup = new MyPopup; if (popup->init(value)) { popup->autorelease(); return popup; } delete popup; return nullptr; } protected: bool init(int value) { if (!Popup::init(320.f, 160.f)) return false; auto node = CCLabelBMFont::create("Hi", "bigFont.fnt"); this->addChild(node); return true; } }; ``` -------------------------------- ### Create an Infinite Fibonacci Generator Source: https://github.com/geode-sdk/docs/blob/main/tutorials/coroutines.md An example of an infinite generator that yields Fibonacci numbers. The loop in the caller determines when to stop. ```cpp #include coro::Generator fibbonacci() { int a = 0; int b = 1; while (true) { co_yield a; auto next = a + b; a = b; b = next; } } for (int num : fibbonacci()) { if (num > 1000) break; log::info("My number: {}", num); } ``` -------------------------------- ### Correct Class Declaration Source: https://github.com/geode-sdk/docs/blob/main/source/styling.md Class names should be in PascalCase. The class declaration, including the name and opening brace, should start on the same line. ```cpp // Correct class BasedButton { }; ``` ```cpp // Wrong class BasedButton { }; ``` -------------------------------- ### Minhook Initialization and Hooking Source: https://github.com/geode-sdk/docs/blob/main/tutorials/migrating.md Initializes Minhook, creates a hook for MenuLayer::init, and enables all hooks. The original function pointer is stored in MenuLayer_init_O. ```cpp bool (__thiscall* MenuLayer_init_O)(gd::MenuLayer* self); bool __fastcall MenuLayer_init_H(gd::MenuLayer* self, void*) { if (!MenuLayer_init_O(self)) return false; return true; } // ... MH_Initialize(); MH_CreateHook((void*)base + 0x1907b0, (void*)&MenuLayer_init_H, (void**)&MenuLayer_init_O); MH_EnableHook(MH_ALL_HOOKS); ``` -------------------------------- ### Declare Mod Dependency Source: https://github.com/geode-sdk/docs/blob/main/mods/dependencies.md Add this to your `mod.json` to declare a required dependency on another mod. Geode will ensure the dependency is installed and available. ```json { "dependencies": { "hjfod.gmd-api": ">=v1.0.0" } } ``` -------------------------------- ### Log a Warning Message Source: https://github.com/geode-sdk/docs/blob/main/tutorials/logging.md Use this to warn about non-critical failures that can be recovered from or retried. For example, a failed API request that the mod will retry. ```cpp geode::log::warn("I failed to fetch this list of items, but I'll retry a few times"); ``` -------------------------------- ### Creating a Button with a Callback Source: https://github.com/geode-sdk/docs/blob/main/handbook/vol2/chap2_5.md This C++ code demonstrates how to create a button (CCMenuItemSpriteExtra) and assign a callback function to it. The `menu_selector` macro is used for convenience. ```cpp auto button = CCMenuItemSpriteExtra::create( ..., this, menu_selector(ThisClass::onButtonClicked) ); ``` -------------------------------- ### Fish Shell Environment Variable Syntax Source: https://github.com/geode-sdk/docs/blob/main/getting-started/ide-setup.md Example of how to set environment variables in Fish shell, which uses a different syntax than standard Bash. ```fish set -gx VAR value ``` -------------------------------- ### Setting Hook Priorities Source: https://github.com/geode-sdk/docs/blob/main/tutorials/hookpriority.md Demonstrates how to set hook priorities for different functions using `setHookPriorityPost`, `setHookPriorityPre`, and `setHookPriorityAfterPost`. Use this to control the execution order of your hooks. ```cpp class $modify(cocos2d::CCLabelBMFont) { static void onModify(auto& self) { if (!self.setHookPriorityPost("cocos2d::CCLabelBMFont::init", Priority::First)) { geode::log::warn("Failed to set hook priority."); } if (!self.setHookPriorityPre("cocos2d::CCLabelBMFont::setString", Priority::Late)) { geode::log::warn("Failed to set hook priority."); } if (!self.setHookPriorityAfterPost("cocos2d::CCLabelBMFont::limitLabelWidth", "geode.node-ids")) { geode::log::warn("Failed to set hook priority."); } } }; ``` -------------------------------- ### Migrating to Modify Class Source: https://github.com/geode-sdk/docs/blob/main/tutorials/migrating.md Example of migrating a hook to a 'Modify' class, simplifying the function signature and calling the original function using the class name. ```cpp class $modify(MenuLayer) { bool init() { if (!MenuLayer::init()) return false; return true; } } ``` -------------------------------- ### Dangling Reference Example Source: https://github.com/geode-sdk/docs/blob/main/cpp/tips.md This code demonstrates a common error where a reference points to memory that has been deallocated, leading to a crash. Ensure the object outlives the reference. ```cpp struct SomeThing { int& m_num; }; SomeThing* thing; { int x = 5; thing = new SomeThing { x }; } thing->m_num; // Whoops! x is out of scope and so what // m_num is referencing has been deallocated ```