Recipes API

This commit is contained in:
TheBrokenRail 2022-06-27 14:47:55 -04:00
parent 329f92c0a4
commit 699d83c61b
13 changed files with 234 additions and 59 deletions

View File

@ -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!

14
example-mods/recipes/.gitignore vendored Normal file
View File

@ -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_*

View File

@ -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)

View File

@ -0,0 +1,52 @@
// Headers
#include <libreborn/libreborn.h>
#include <symbols/minecraft.h>
#include <mods/misc/misc.h>
// 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);
}

View File

@ -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);
}

View File

@ -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)

View File

@ -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);

View File

@ -3,6 +3,7 @@
#include <mods/init/init.h>
#include <mods/feature/feature.h>
#include <mods/misc/misc.h>
#include <mods/creative/creative.h>
#ifndef MCPI_SERVER_MODE

100
mods/src/misc/api.cpp Normal file
View File

@ -0,0 +1,100 @@
#include <vector>
#include <libreborn/libreborn.h>
#include <symbols/minecraft.h>
#include <mods/misc/misc.h>
#include "misc-internal.h"
// Run Functions On Update
static std::vector<misc_update_function_t> &get_misc_update_functions() {
static std::vector<misc_update_function_t> 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<misc_update_function_t> &get_misc_tick_functions() {
static std::vector<misc_update_function_t> 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<misc_update_function_t> &get_misc_recipes_setup_functions() {
static std::vector<misc_update_function_t> 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<misc_update_function_t> &get_misc_furnace_recipes_setup_functions() {
static std::vector<misc_update_function_t> 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);
}

View File

@ -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
}

View File

@ -258,4 +258,5 @@ void init_misc() {
// Init C++ And Logging
_init_misc_cpp();
_init_misc_logging();
_init_misc_api();
}

View File

@ -1,7 +1,6 @@
#include <string>
#include <fstream>
#include <streambuf>
#include <vector>
#include <cstring>
@ -26,44 +25,6 @@ static AppPlatform_readAssetFile_return_value AppPlatform_readAssetFile_injectio
return ret;
}
// Run Functions On Update
static std::vector<misc_update_function_t> &get_misc_update_functions() {
static std::vector<misc_update_function_t> 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<misc_update_function_t> &get_misc_tick_functions() {
static std::vector<misc_update_function_t> 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

View File

@ -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<Recipes_Type> 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