From 699d83c61b9c34499fb9d238a00779c75eee2475 Mon Sep 17 00:00:00 2001 From: TheBrokenRail Date: Mon, 27 Jun 2022 14:47:55 -0400 Subject: [PATCH] Recipes API --- example-mods/README.md | 1 + example-mods/recipes/.gitignore | 14 +++ example-mods/recipes/CMakeLists.txt | 15 +++ example-mods/recipes/recipes.cpp | 52 +++++++++ .../gles/src/compatibility-layer/draw.c | 27 +++-- mods/CMakeLists.txt | 2 +- mods/include/mods/misc/misc.h | 8 +- mods/src/creative/creative.cpp | 1 + mods/src/misc/api.cpp | 100 ++++++++++++++++++ mods/src/misc/misc-internal.h | 1 + mods/src/misc/misc.c | 1 + mods/src/misc/misc.cpp | 44 -------- symbols/include/symbols/minecraft.h | 27 +++++ 13 files changed, 234 insertions(+), 59 deletions(-) create mode 100644 example-mods/recipes/.gitignore create mode 100644 example-mods/recipes/CMakeLists.txt create mode 100644 example-mods/recipes/recipes.cpp create mode 100644 mods/src/misc/api.cpp diff --git a/example-mods/README.md b/example-mods/README.md index 3f4f2a3ba..926f6126e 100644 --- a/example-mods/README.md +++ b/example-mods/README.md @@ -3,6 +3,7 @@ This is an example of a mod that cane be built using the modding SDK. * **Expanded Creative Mod**: This specific mod adds even more items and blocks to the Creative Inventory. It was originally by [@Bigjango13](https://github.com/bigjango13). * **Chat Commands Mod**: This specific mod makes an chat message starting with a ``/`` handled by the MCPI API. +* **Recipes Mod**: This specific mod demos custom recipes. ## The SDK The modding SDK is a collection of exported CMake targets that allows anyone to create their own MCPI mod! diff --git a/example-mods/recipes/.gitignore b/example-mods/recipes/.gitignore new file mode 100644 index 000000000..8563b9852 --- /dev/null +++ b/example-mods/recipes/.gitignore @@ -0,0 +1,14 @@ +out +debian/tmp +.vscode +build* +CMakeLists.txt.user +*.autosave +AppImageBuilder.yml +appimage-builder-cache +appimage-build +AppDir +*.zsync +*.AppImage +core* +qemu_* diff --git a/example-mods/recipes/CMakeLists.txt b/example-mods/recipes/CMakeLists.txt new file mode 100644 index 000000000..cdf6bce89 --- /dev/null +++ b/example-mods/recipes/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.16.0) + +# Build For ARM +set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc) +set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++) + +# Start Project +project(recipes) + +# Include SDK +include("$ENV{HOME}/.minecraft-pi/sdk/lib/minecraft-pi-reborn-client/sdk/sdk.cmake") + +# Build +add_library(recipes SHARED recipes.cpp) +target_link_libraries(recipes mods-headers reborn-util symbols misc) diff --git a/example-mods/recipes/recipes.cpp b/example-mods/recipes/recipes.cpp new file mode 100644 index 000000000..f0e6aca0e --- /dev/null +++ b/example-mods/recipes/recipes.cpp @@ -0,0 +1,52 @@ +// Headers + +#include +#include +#include + +// Custom Crafting Recipes +static void Recipes_injection(unsigned char *recipes) { + // Add + Recipes_Type type1 = { + .item = 0, + .tile = 0, + .instance = { + .count = 1, + .id = 12, + .auxiliary = 0 + }, + .letter = 'a' + }; + Recipes_Type type2 = { + .item = 0, + .tile = 0, + .instance = { + .count = 1, + .id = 13, + .auxiliary = 0 + }, + .letter = 'b' + }; + ItemInstance result = { + .count = 1, + .id = 344, + .auxiliary = 0 + }; + (*Recipes_addShapelessRecipe)(recipes, result, {type1, type2}); +} + +// Custom Furnace Recipes +static void FurnaceRecipes_injection(unsigned char *recipes) { + // Add + (*FurnaceRecipes_addFurnaceRecipe)(recipes, 49, {.count = 1, .id = 246, .auxiliary = 0}); +} + +// Init +__attribute__((constructor)) static void init_recipes() { + // Log + INFO("Loading Custom Recipes"); + + // Setup + misc_run_on_recipes_setup(Recipes_injection); + misc_run_on_furnace_recipes_setup(FurnaceRecipes_injection); +} diff --git a/media-layer/gles/src/compatibility-layer/draw.c b/media-layer/gles/src/compatibility-layer/draw.c index b7c4253a5..f0c21447a 100644 --- a/media-layer/gles/src/compatibility-layer/draw.c +++ b/media-layer/gles/src/compatibility-layer/draw.c @@ -157,6 +157,11 @@ static void use_shader(GLuint program) { // Array Pointer Drawing GL_FUNC(glDrawArrays, void, (GLenum mode, GLint first, GLsizei count)); +#define lazy_uniform(name) \ + static GLint name##_handle = -1; \ + if (name##_handle == -1) { \ + name##_handle = real_glGetUniformLocation()(program, #name); \ + } void glDrawArrays(GLenum mode, GLint first, GLsizei count) { // Verify if (gl_state.array_pointers.vertex.size != 3 || !gl_state.array_pointers.vertex.enabled || gl_state.array_pointers.vertex.type != GL_FLOAT) { @@ -178,30 +183,30 @@ void glDrawArrays(GLenum mode, GLint first, GLsizei count) { use_shader(program); // Projection Matrix - GLint u_projection_handle = real_glGetUniformLocation()(program, "u_projection"); + lazy_uniform(u_projection); matrix_t *p = &gl_state.matrix_stacks.projection.stack[gl_state.matrix_stacks.projection.i]; real_glUniformMatrix4fv()(u_projection_handle, 1, 0, (GLfloat *) &p->data[0][0]); // Model View Matrix - GLint u_model_view_handle = real_glGetUniformLocation()(program, "u_model_view"); + lazy_uniform(u_model_view); p = &gl_state.matrix_stacks.model_view.stack[gl_state.matrix_stacks.model_view.i]; real_glUniformMatrix4fv()(u_model_view_handle, 1, 0, (GLfloat *) &p->data[0][0]); // Has Texture - GLint u_has_texture_handle = real_glGetUniformLocation()(program, "u_has_texture"); \ + lazy_uniform(u_has_texture); \ real_glUniform1i()(u_has_texture_handle, use_texture); \ // Texture Matrix - GLint u_texture_handle = real_glGetUniformLocation()(program, "u_texture"); + lazy_uniform(u_texture); p = &gl_state.matrix_stacks.texture.stack[gl_state.matrix_stacks.texture.i]; real_glUniformMatrix4fv()(u_texture_handle, 1, 0, (GLfloat *) &p->data[0][0]); // Texture Unit - GLint u_texture_unit_handle = real_glGetUniformLocation()(program, "u_texture_unit"); + lazy_uniform(u_texture_unit); real_glUniform1i()(u_texture_unit_handle, 0); // Alpha Test - GLint u_alpha_test_handle = real_glGetUniformLocation()(program, "u_alpha_test"); + lazy_uniform(u_alpha_test); real_glUniform1i()(u_alpha_test_handle, gl_state.alpha_test); // Color @@ -214,16 +219,16 @@ void glDrawArrays(GLenum mode, GLint first, GLsizei count) { } // Fog - GLint u_fog_handle = real_glGetUniformLocation()(program, "u_fog"); + lazy_uniform(u_fog); real_glUniform1i()(u_fog_handle, gl_state.fog.enabled); if (gl_state.fog.enabled) { - GLint u_fog_color_handle = real_glGetUniformLocation()(program, "u_fog_color"); + lazy_uniform(u_fog_color); real_glUniform4f()(u_fog_color_handle, gl_state.fog.color[0], gl_state.fog.color[1], gl_state.fog.color[2], gl_state.fog.color[3]); - GLint u_fog_is_linear_handle = real_glGetUniformLocation()(program, "u_fog_is_linear"); + lazy_uniform(u_fog_is_linear); real_glUniform1i()(u_fog_is_linear_handle, gl_state.fog.mode == GL_LINEAR); - GLint u_fog_start_handle = real_glGetUniformLocation()(program, "u_fog_start"); + lazy_uniform(u_fog_start); real_glUniform1f()(u_fog_start_handle, gl_state.fog.start); - GLint u_fog_end_handle = real_glGetUniformLocation()(program, "u_fog_end"); + lazy_uniform(u_fog_end); real_glUniform1f()(u_fog_end_handle, gl_state.fog.end); } diff --git a/mods/CMakeLists.txt b/mods/CMakeLists.txt index 28e330929..a4c736719 100644 --- a/mods/CMakeLists.txt +++ b/mods/CMakeLists.txt @@ -78,7 +78,7 @@ endif() add_library(death SHARED src/death/death.cpp) target_link_libraries(death mods-headers reborn-patch symbols feature) -add_library(misc SHARED src/misc/misc.c src/misc/misc.cpp src/misc/logging.cpp) +add_library(misc SHARED src/misc/misc.c src/misc/misc.cpp src/misc/logging.cpp src/misc/api.cpp) target_link_libraries(misc mods-headers reborn-patch symbols media-layer-core feature GLESv1_CM) add_library(options SHARED src/options/options.c src/options/options.cpp) diff --git a/mods/include/mods/misc/misc.h b/mods/include/mods/misc/misc.h index 3995ae293..4c66d8dc7 100644 --- a/mods/include/mods/misc/misc.h +++ b/mods/include/mods/misc/misc.h @@ -4,9 +4,11 @@ extern "C" { #endif -typedef void (*misc_update_function_t)(unsigned char *minecraft); -void misc_run_on_update(misc_update_function_t function); -void misc_run_on_tick(misc_update_function_t function); +typedef void (*misc_update_function_t)(unsigned char *obj); +void misc_run_on_update(misc_update_function_t function); // obj == Minecraft * +void misc_run_on_tick(misc_update_function_t function); // obj == Minecraft * +void misc_run_on_recipes_setup(misc_update_function_t function); // obj == Recipes * +void misc_run_on_furnace_recipes_setup(misc_update_function_t function); // obj == FurnaceRecipes * void Level_saveLevelData_injection(unsigned char *level); diff --git a/mods/src/creative/creative.cpp b/mods/src/creative/creative.cpp index b4b75fae1..53e8e1b1f 100644 --- a/mods/src/creative/creative.cpp +++ b/mods/src/creative/creative.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #ifndef MCPI_SERVER_MODE diff --git a/mods/src/misc/api.cpp b/mods/src/misc/api.cpp new file mode 100644 index 000000000..7ab075758 --- /dev/null +++ b/mods/src/misc/api.cpp @@ -0,0 +1,100 @@ +#include + +#include +#include + +#include +#include "misc-internal.h" + +// Run Functions On Update +static std::vector &get_misc_update_functions() { + static std::vector functions; + return functions; +} +void misc_run_on_update(misc_update_function_t function) { + get_misc_update_functions().push_back(function); +} +// Handle Custom Update Behavior +static void Minecraft_update_injection(unsigned char *minecraft) { + // Call Original Method + (*Minecraft_update)(minecraft); + + // Run Functions + for (misc_update_function_t function : get_misc_update_functions()) { + (*function)(minecraft); + } +} + +// Run Functions On Tick +static std::vector &get_misc_tick_functions() { + static std::vector functions; + return functions; +} +void misc_run_on_tick(misc_update_function_t function) { + get_misc_tick_functions().push_back(function); +} +// Handle Custom Tick Behavior +static void Minecraft_tick_injection(unsigned char *minecraft, int32_t param_1, int32_t param_2) { + // Call Original Method + (*Minecraft_tick)(minecraft, param_1, param_2); + + // Run Functions + for (misc_update_function_t function : get_misc_tick_functions()) { + (*function)(minecraft); + } +} + +// Run Functions On Recipes Setup +static std::vector &get_misc_recipes_setup_functions() { + static std::vector functions; + return functions; +} +void misc_run_on_recipes_setup(misc_update_function_t function) { + get_misc_recipes_setup_functions().push_back(function); +} +// Handle Custom Recipes Setup Behavior +static unsigned char *Recipes_injection(unsigned char *recipes) { + // Call Original Method + (*Recipes)(recipes); + + // Run Functions + for (misc_update_function_t function : get_misc_recipes_setup_functions()) { + (*function)(recipes); + } + + // Return + return recipes; +} + +// Run Functions On Furnace Recipes Setup +static std::vector &get_misc_furnace_recipes_setup_functions() { + static std::vector functions; + return functions; +} +void misc_run_on_furnace_recipes_setup(misc_update_function_t function) { + get_misc_furnace_recipes_setup_functions().push_back(function); +} +// Handle Custom Furnace Recipes Setup Behavior +static unsigned char *FurnaceRecipes_injection(unsigned char *recipes) { + // Call Original Method + (*FurnaceRecipes)(recipes); + + // Run Functions + for (misc_update_function_t function : get_misc_furnace_recipes_setup_functions()) { + (*function)(recipes); + } + + // Return + return recipes; +} + +// Init +void _init_misc_api() { + // Handle Custom Update Behavior + overwrite_calls((void *) Minecraft_update, (void *) Minecraft_update_injection); + // Handle Custom Tick Behavior + overwrite_calls((void *) Minecraft_tick, (void *) Minecraft_tick_injection); + // Handle Custom Recipe Setup Behavior + overwrite_calls((void *) Recipes, (void *) Recipes_injection); + overwrite_calls((void *) FurnaceRecipes, (void *) FurnaceRecipes_injection); +} diff --git a/mods/src/misc/misc-internal.h b/mods/src/misc/misc-internal.h index 16cff902f..3f9e88539 100644 --- a/mods/src/misc/misc-internal.h +++ b/mods/src/misc/misc-internal.h @@ -6,6 +6,7 @@ extern "C" { __attribute__((visibility("internal"))) void _init_misc_cpp(); __attribute__((visibility("internal"))) void _init_misc_logging(); +__attribute__((visibility("internal"))) void _init_misc_api(); #ifdef __cplusplus } diff --git a/mods/src/misc/misc.c b/mods/src/misc/misc.c index 4750462d0..187a86320 100644 --- a/mods/src/misc/misc.c +++ b/mods/src/misc/misc.c @@ -258,4 +258,5 @@ void init_misc() { // Init C++ And Logging _init_misc_cpp(); _init_misc_logging(); + _init_misc_api(); } diff --git a/mods/src/misc/misc.cpp b/mods/src/misc/misc.cpp index 3fce748ed..0318b497f 100644 --- a/mods/src/misc/misc.cpp +++ b/mods/src/misc/misc.cpp @@ -1,7 +1,6 @@ #include #include #include -#include #include @@ -26,44 +25,6 @@ static AppPlatform_readAssetFile_return_value AppPlatform_readAssetFile_injectio return ret; } -// Run Functions On Update -static std::vector &get_misc_update_functions() { - static std::vector functions; - return functions; -} -void misc_run_on_update(misc_update_function_t function) { - get_misc_update_functions().push_back(function); -} -// Handle Custom Update Behavior -static void Minecraft_update_injection(unsigned char *minecraft) { - // Call Original Method - (*Minecraft_update)(minecraft); - - // Run Functions - for (misc_update_function_t function : get_misc_update_functions()) { - (*function)(minecraft); - } -} - -// Run Functions On Update -static std::vector &get_misc_tick_functions() { - static std::vector functions; - return functions; -} -void misc_run_on_tick(misc_update_function_t function) { - get_misc_tick_functions().push_back(function); -} -// Handle Custom Tick Behavior -static void Minecraft_tick_injection(unsigned char *minecraft, int32_t param_1, int32_t param_2) { - // Call Original Method - (*Minecraft_tick)(minecraft, param_1, param_2); - - // Run Functions - for (misc_update_function_t function : get_misc_tick_functions()) { - (*function)(minecraft); - } -} - // Add Missing Buttons To Pause Menu static void PauseScreen_init_injection(unsigned char *screen) { // Call Original Method @@ -105,11 +66,6 @@ void _init_misc_cpp() { overwrite((void *) AppPlatform_readAssetFile, (void *) AppPlatform_readAssetFile_injection); } - // Handle Custom Update Behavior - overwrite_calls((void *) Minecraft_update, (void *) Minecraft_update_injection); - // Handle Custom Tick Behavior - overwrite_calls((void *) Minecraft_tick, (void *) Minecraft_tick_injection); - // Fix Pause Menu if (feature_has("Fix Pause Menu", server_disabled)) { // Add Missing Buttons To Pause Menu diff --git a/symbols/include/symbols/minecraft.h b/symbols/include/symbols/minecraft.h index 1ab712895..3142a9028 100644 --- a/symbols/include/symbols/minecraft.h +++ b/symbols/include/symbols/minecraft.h @@ -722,6 +722,23 @@ static SoundEngine_update_t SoundEngine_update = (SoundEngine_update_t) 0x67778; static uint32_t SoundEngine_minecraft_property_offset = 0xa08; // Minecraft * static uint32_t SoundEngine_options_property_offset = 0x4; // Options * +// Recipes + +// If there are multiple item IDs, the priority order is: "item" > "tile" > "instance" +typedef struct { + unsigned char *item; + unsigned char *tile; + ItemInstance instance; + char letter; +} Recipes_Type; + +typedef unsigned char *(*Recipes_t)(unsigned char *recipes); +static Recipes_t Recipes = (Recipes_t) 0x9cabc; + +// FurnaceRecipes + +static Recipes_t FurnaceRecipes = (Recipes_t) 0xa0778; + // Method That Require C++ Types #ifdef __cplusplus @@ -848,6 +865,16 @@ static OptionsPane_unknown_toggle_creating_function_t OptionsPane_unknown_toggle typedef void (*Textures_loadAndBindTexture_t)(unsigned char *textures, std::string const& name); static Textures_loadAndBindTexture_t Textures_loadAndBindTexture = (Textures_loadAndBindTexture_t) 0x539cc; +// Recipes + +typedef void (*Recipes_addShapelessRecipe_t)(unsigned char *recipes, ItemInstance const& result, std::vector const& param_2); +static Recipes_addShapelessRecipe_t Recipes_addShapelessRecipe = (Recipes_addShapelessRecipe_t) 0x9c3dc; + +// FurnaceRecipes + +typedef void (*FurnaceRecipes_addFurnaceRecipe_t)(unsigned char *recipes, int32_t input_item_id, ItemInstance const& result); +static FurnaceRecipes_addFurnaceRecipe_t FurnaceRecipes_addFurnaceRecipe = (FurnaceRecipes_addFurnaceRecipe_t) 0xa0714; + #endif #pragma GCC diagnostic pop