Add Buckets

This commit is contained in:
TheBrokenRail 2022-07-10 10:37:19 -04:00
parent b3b935dd1d
commit 68519f06fd
17 changed files with 530 additions and 118 deletions

View File

@ -137,9 +137,14 @@ add_subdirectory(dependencies)
# Warnings
add_compile_options(-Wall -Wextra -Werror -Wpointer-arith -Wshadow -Wnull-dereference)
if(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 10.0)
if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
# Prevents False Positives
if(CMAKE_C_COMPILER_VERSION VERSION_GREATER 10.0)
add_compile_options(-Wno-stringop-overflow)
endif()
if(CMAKE_C_COMPILER_VERSION VERSION_GREATER 11.0)
add_compile_options(-Wno-array-bounds -Wno-stringop-overread)
endif()
endif()
add_link_options(-Wl,--no-undefined)
add_definitions(-D_GNU_SOURCE)

View File

@ -12,4 +12,4 @@ include("$ENV{HOME}/.minecraft-pi/sdk/lib/minecraft-pi-reborn-client/sdk/sdk.cma
# Build
add_library(expanded-creative SHARED expanded-creative.cpp)
target_link_libraries(expanded-creative mods-headers reborn-patch symbols)
target_link_libraries(expanded-creative mods-headers reborn-patch symbols misc)

View File

@ -3,14 +3,11 @@
#include <libreborn/libreborn.h>
#include <symbols/minecraft.h>
#include <mods/init/init.h>
#include <mods/misc/misc.h>
// The Actual Mod
static FillingContainer_addItem_t original_mod;
static int32_t Inventory_setupDefault_FillingContainer_addItem_call_injection(unsigned char *filling_container, ItemInstance *item_instance) {
// Call Original Modified Method
int32_t ret = (*original_mod)(filling_container, item_instance);
static void Inventory_setupDefault_FillingContainer_addItem_call_injection(unsigned char *filling_container) {
ItemInstance *fire_instance = new ItemInstance;
ALLOC_CHECK(fire_instance);
fire_instance->count = 255;
@ -633,9 +630,6 @@ static int32_t Inventory_setupDefault_FillingContainer_addItem_call_injection(un
chickenRaw_instance->auxiliary = 0;
chickenRaw_instance->id = 365;
(*FillingContainer_addItem)(filling_container, chickenRaw_instance);
// Return
return ret;
}
// Init
@ -645,7 +639,5 @@ HOOK(init_creative, void, ()) {
INFO("Loading Expanded Creative Mod");
void *point = (void *) 0x8e0fc;
original_mod = (FillingContainer_addItem_t) extract_from_bl_instruction((unsigned char *) point);
overwrite_call(point, (void *) Inventory_setupDefault_FillingContainer_addItem_call_injection);
misc_run_on_creative_inventory_setup(Inventory_setupDefault_FillingContainer_addItem_call_injection);
}

View File

@ -38,3 +38,4 @@ TRUE Force Touch GUI Button Behavior
TRUE Improved Button Hover Behavior
TRUE Implement Create World Dialog
TRUE Remove Forced GUI Lag
TRUE Add Buckets

View File

@ -11,17 +11,11 @@
#include "api.h"
// Store Audio Sources
static std::vector<ALuint> &get_sources() {
static std::vector<ALuint> sources;
return sources;
}
static std::vector<ALuint> sources;
// Store Idle Audio Sources
#define MAX_IDLE_SOURCES 50
static std::vector<ALuint> &get_idle_sources() {
static std::vector<ALuint> sources;
return sources;
}
static std::vector<ALuint> idle_sources;
// Error Checking
#define AL_ERROR_CHECK() AL_ERROR_CHECK_MANUAL(alGetError())
@ -36,17 +30,17 @@ static std::vector<ALuint> &get_idle_sources() {
// Delete Sources
void _media_audio_delete_sources() {
if (_media_audio_is_loaded()) {
for (ALuint source : get_idle_sources()) {
for (ALuint source : idle_sources) {
alDeleteSources(1, &source);
AL_ERROR_CHECK();
}
for (ALuint source : get_sources()) {
for (ALuint source : sources) {
alDeleteSources(1, &source);
AL_ERROR_CHECK();
}
}
get_idle_sources().clear();
get_sources().clear();
idle_sources.clear();
sources.clear();
}
// Update Listener
@ -68,8 +62,8 @@ void media_audio_update(float volume, float x, float y, float z, float yaw) {
AL_ERROR_CHECK();
// Clear Finished Sources
std::vector<ALuint>::iterator it = get_sources().begin();
while (it != get_sources().end()) {
std::vector<ALuint>::iterator it = sources.begin();
while (it != sources.end()) {
ALuint source = *it;
bool remove = false;
// Check
@ -81,8 +75,8 @@ void media_audio_update(float volume, float x, float y, float z, float yaw) {
if (source_state != AL_PLAYING) {
// Finished Playing
remove = true;
if (get_idle_sources().size() < MAX_IDLE_SOURCES) {
get_idle_sources().push_back(source);
if (idle_sources.size() < MAX_IDLE_SOURCES) {
idle_sources.push_back(source);
} else {
alDeleteSources(1, &source);
AL_ERROR_CHECK();
@ -94,7 +88,7 @@ void media_audio_update(float volume, float x, float y, float z, float yaw) {
}
// Remove If Needed
if (remove) {
it = get_sources().erase(it);
it = sources.erase(it);
} else {
++it;
}
@ -111,10 +105,10 @@ void media_audio_play(const char *source, const char *name, float x, float y, fl
if (volume > 0.0f && buffer) {
// Get Source
ALuint al_source;
if (get_idle_sources().size() > 0) {
if (idle_sources.size() > 0) {
// Use Idle Source
al_source = get_idle_sources().back();
get_idle_sources().pop_back();
al_source = idle_sources.back();
idle_sources.pop_back();
} else {
// Create Source
alGenSources(1, &al_source);
@ -160,7 +154,7 @@ void media_audio_play(const char *source, const char *name, float x, float y, fl
// Play
alSourcePlay(al_source);
AL_ERROR_CHECK();
get_sources().push_back(al_source);
sources.push_back(al_source);
}
}
}

View File

@ -29,7 +29,7 @@ add_library(chat SHARED src/chat/chat.cpp src/chat/ui.c)
target_link_libraries(chat mods-headers reborn-patch symbols feature)
add_library(creative SHARED src/creative/creative.cpp)
target_link_libraries(creative mods-headers reborn-patch symbols feature)
target_link_libraries(creative mods-headers reborn-patch symbols feature misc)
add_library(game-mode SHARED src/game-mode/game-mode.c src/game-mode/ui.cpp)
target_link_libraries(game-mode mods-headers reborn-patch symbols feature)
@ -54,7 +54,7 @@ else()
target_link_libraries(camera mods-headers reborn-patch symbols media-layer-core feature home)
add_library(input SHARED src/input/input.cpp src/input/bow.c src/input/attack.c src/input/toggle.c src/input/misc.c src/input/drop.cpp)
target_link_libraries(input mods-headers reborn-patch symbols creative feature media-layer-core)
target_link_libraries(input mods-headers reborn-patch symbols creative feature misc media-layer-core)
add_library(sign SHARED src/sign/sign.cpp)
target_link_libraries(sign mods-headers reborn-patch symbols feature input)
@ -84,6 +84,9 @@ target_link_libraries(misc mods-headers reborn-patch symbols media-layer-core fe
add_library(options SHARED src/options/options.c src/options/options.cpp)
target_link_libraries(options mods-headers reborn-patch symbols feature home)
add_library(bucket SHARED src/bucket/bucket.cpp)
target_link_libraries(bucket mods-headers reborn-patch symbols feature misc)
add_library(home SHARED src/home/home.c)
target_link_libraries(home mods-headers reborn-patch symbols)
@ -91,7 +94,7 @@ add_library(test SHARED src/test/test.c)
target_link_libraries(test mods-headers reborn-patch home)
add_library(init SHARED src/init/init.c)
target_link_libraries(init mods-headers compat game-mode misc death options chat creative home version test media-layer-core)
target_link_libraries(init mods-headers compat game-mode misc death options chat creative bucket home version test media-layer-core)
if(MCPI_SERVER_MODE)
target_link_libraries(init server)
else()
@ -99,7 +102,7 @@ else()
endif()
## Install Mods
set(MODS_TO_INSTALL init compat readdir feature game-mode misc override death options chat creative home version test)
set(MODS_TO_INSTALL init compat readdir feature game-mode misc override death options chat creative bucket home version test)
if(MCPI_SERVER_MODE)
list(APPEND MODS_TO_INSTALL server)
else()

View File

@ -27,6 +27,7 @@ void init_misc();
void init_death();
void init_options();
void init_chat();
void init_bucket();
void init_home();
#ifndef MCPI_SERVER_MODE
void init_benchmark();

View File

@ -1,14 +1,21 @@
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
int32_t misc_get_real_selected_slot(unsigned char *player);
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 misc_run_on_creative_inventory_setup(misc_update_function_t function); // obj == FillingContainer *
void misc_run_on_tiles_setup(misc_update_function_t function); // obj == NULL
void misc_run_on_items_setup(misc_update_function_t function); // obj == NULL
void Level_saveLevelData_injection(unsigned char *level);

View File

@ -0,0 +1,2 @@
# ``bucket`` Mod
This mod adds buckets.

310
mods/src/bucket/bucket.cpp Normal file
View File

@ -0,0 +1,310 @@
#include <libreborn/libreborn.h>
#include <symbols/minecraft.h>
#include <mods/feature/feature.h>
#include <mods/init/init.h>
#include <mods/misc/misc.h>
// Items
unsigned char *bucket = NULL;
// Description And Texture
static std::string BucketItem_getDescriptionId(__attribute__((unused)) unsigned char *item, const ItemInstance *item_instance) {
if (item_instance->auxiliary == *(int32_t *) (*Tile_water + Tile_id_property_offset)) {
return "item.bucketWater";
} else if (item_instance->auxiliary == *(int32_t *) (*Tile_lava + Tile_id_property_offset)) {
return "item.bucketLava";
} else {
return "item.bucket";
}
}
static int32_t BucketItem_getIcon(__attribute__((unused)) unsigned char *item, int32_t auxiliary) {
if (auxiliary == *(int32_t *) (*Tile_water + Tile_id_property_offset)) {
return 75;
} else if (auxiliary == *(int32_t *) (*Tile_lava + Tile_id_property_offset)) {
return 76;
} else {
return 74;
}
}
// Use Bucket
static int32_t BucketItem_useOn(__attribute__((unused)) unsigned char *item, ItemInstance *item_instance, unsigned char *player, unsigned char *level, int32_t x, int32_t y, int32_t z, int32_t hit_side, __attribute__((unused)) float hit_x, __attribute__((unused)) float hit_y, __attribute__((unused)) float hit_z) {
if (item_instance->count < 1) {
return 0;
}
if (item_instance->auxiliary == 0) {
// Empty Bucket
int32_t new_auxiliary = 0;
int32_t tile = (*Level_getTile)(level, x, y, z);
if (tile == *(int32_t *) (*Tile_calmWater + Tile_id_property_offset)) {
new_auxiliary = *(int32_t *) (*Tile_water + Tile_id_property_offset);
} else if (tile == *(int32_t *) (*Tile_calmLava + Tile_id_property_offset)) {
new_auxiliary = *(int32_t *) (*Tile_water + Tile_id_property_offset);
}
if (new_auxiliary != 0) {
// Valid
bool success = false;
if (item_instance->count == 1) {
item_instance->auxiliary = new_auxiliary;
success = true;
} else {
ItemInstance new_item;
new_item.id = *(int32_t *) (bucket + Item_id_property_offset);
new_item.count = 1;
new_item.auxiliary = new_auxiliary;
unsigned char *inventory = *(unsigned char **) (player + Player_inventory_property_offset);
unsigned char *inventory_vtable = *(unsigned char **) inventory;
FillingContainer_add_t FillingContainer_add = *(FillingContainer_add_t *) (inventory_vtable + FillingContainer_add_vtable_offset);
if ((*FillingContainer_add)(inventory, &new_item)) {
// Added To Inventory
success = true;
item_instance->count -= 1;
}
}
if (success) {
(*Level_setTileAndData)(level, x, y, z, 0, 0);
return 1;
} else {
return 0;
}
} else {
// Invalid
return 0;
}
} else {
// Place
switch (hit_side) {
case 0: {
y -= 1;
break;
}
case 1: {
y += 1;
break;
}
case 2: {
z -= 1;
break;
}
case 3: {
z += 1;
break;
}
case 4: {
x -= 1;
break;
}
case 5: {
x += 1;
break;
}
}
// Get Current Tile
bool valid = false;
unsigned char *material = (*Level_getMaterial)(level, x, y, z);
if (material != NULL) {
unsigned char *material_vtable = *(unsigned char **) material;
Material_isSolid_t Material_isSolid = *(Material_isSolid_t *) (material_vtable + Material_isSolid_vtable_offset);
valid = !(*Material_isSolid)(material);
}
if (valid) {
(*Level_setTileAndData)(level, x, y, z, item_instance->auxiliary, 0);
item_instance->auxiliary = 0;
return 1;
} else {
return 0;
}
}
}
// Bucket VTable
static unsigned char *get_bucket_vtable() {
static unsigned char *vtable = NULL;
if (vtable == NULL) {
// Init
vtable = (unsigned char *) malloc(ITEM_VTABLE_SIZE);
ALLOC_CHECK(vtable);
// Copy Old VTable
memcpy((void *) vtable, (void *) Item_vtable, ITEM_VTABLE_SIZE);
// Modify
*(Item_getDescriptionId_t *) (vtable + Item_getDescriptionId_vtable_offset) = BucketItem_getDescriptionId;
*(Item_getIcon_t *) (vtable + Item_getIcon_vtable_offset) = BucketItem_getIcon;
*(Item_useOn_t *) (vtable + Item_useOn_vtable_offset) = BucketItem_useOn;
}
return vtable;
}
__attribute__((destructor)) static void free_bucket_vtable() {
free(get_bucket_vtable());
}
// Create Items
static unsigned char *create_bucket(int32_t id, int32_t texture_x, int32_t texture_y, const char *name) {
// Construct
unsigned char *item = (unsigned char *) ::operator new(ITEM_SIZE);
ALLOC_CHECK(item);
(*Item)(item, id);
// Set VTable
*(unsigned char **) item = get_bucket_vtable();
// Get Functions
unsigned char *vtable = *(unsigned char **) item;
Item_setIcon_t Item_setIcon = *(Item_setIcon_t *) (vtable + Item_setIcon_vtable_offset);
Item_setDescriptionId_t Item_setDescriptionId = *(Item_setDescriptionId_t *) (vtable + Item_setDescriptionId_vtable_offset);
// Setup
(*Item_setIcon)(item, texture_x, texture_y);
(*Item_setDescriptionId)(item, name);
*(int32_t *) (item + Item_is_stacked_by_data_property_offset) = 1;
*(int32_t *) (item + Item_category_property_offset) = 2;
*(int32_t *) (item + Item_max_damage_property_offset) = 0;
*(int32_t *) (item + Item_max_stack_size_property_offset) = 1;
// Return
return item;
}
static void Item_initItems_injection(__attribute__((unused)) unsigned char *null) {
bucket = create_bucket(69, 10, 4, "bucket");
}
// Change Max Stack Size Based On Auxiliary
static int32_t ItemInstance_getMaxStackSize_injection(ItemInstance *item_instance) {
if (item_instance->id == *(int32_t *) (bucket + Item_id_property_offset) && item_instance->auxiliary == 0) {
// Custom Value
return 16;
} else {
// Call Original Method
return (*ItemInstance_getMaxStackSize)(item_instance);
}
}
// Creative Inventory
static void inventory_add_item(unsigned char *inventory, unsigned char *item, int32_t auxiliary) {
ItemInstance *item_instance = new ItemInstance;
ALLOC_CHECK(item_instance);
item_instance = (*ItemInstance_constructor_item_extra)(item_instance, item, 1, auxiliary);
(*FillingContainer_addItem)(inventory, item_instance);
}
static void Inventory_setupDefault_FillingContainer_addItem_call_injection(unsigned char *filling_container) {
inventory_add_item(filling_container, bucket, 0);
inventory_add_item(filling_container, bucket, *(int32_t *) (*Tile_water + Tile_id_property_offset));
inventory_add_item(filling_container, bucket, *(int32_t *) (*Tile_lava + Tile_id_property_offset));
}
// Make Liquids Selectable
static bool is_holding_bucket = false;
static void Mob_pick_Level_clip_injection(unsigned char *level, unsigned char *param_1, unsigned char *param_2, bool param_3, __attribute__((unused)) bool clip_liquids) {
// Call Original Method
(*Level_clip)(level, param_1, param_2, param_3, is_holding_bucket);
}
static void handle_tick(unsigned char *minecraft) {
unsigned char *player = *(unsigned char **) (minecraft + Minecraft_player_property_offset);
if (player != NULL) {
// Get Selected Slot
int32_t selected_slot = misc_get_real_selected_slot(player);
unsigned char *inventory = *(unsigned char **) (player + Player_inventory_property_offset);
// Prepare
unsigned char *inventory_vtable = *(unsigned char **) inventory;
FillingContainer_getItem_t FillingContainer_getItem = *(FillingContainer_getItem_t *) (inventory_vtable + FillingContainer_getItem_vtable_offset);
// Get Item
ItemInstance *inventory_item = (*FillingContainer_getItem)(inventory, selected_slot);
// Check
is_holding_bucket = inventory_item != NULL && inventory_item->id == (*(int32_t *) (bucket + Item_id_property_offset)) && inventory_item->auxiliary == 0;
}
}
// Prevent Breaking Liquid
static bool is_calm_liquid(int32_t id) {
if (id == *(int32_t *) (*Tile_calmWater + Tile_id_property_offset)) {
return true;
} else if (id == *(int32_t *) (*Tile_calmLava + Tile_id_property_offset)) {
return true;
} else {
return false;
}
}
static void Minecraft_handleMouseDown_injection(unsigned char *minecraft, int param_1, bool can_destroy) {
// Check
unsigned char *level = *(unsigned char **) (minecraft + Minecraft_level_property_offset);
if (level != NULL) {
int32_t x = *(int32_t *) (minecraft + Minecraft_targeted_x_property_offset);
int32_t y = *(int32_t *) (minecraft + Minecraft_targeted_y_property_offset);
int32_t z = *(int32_t *) (minecraft + Minecraft_targeted_z_property_offset);
int32_t tile = (*Level_getTile)(level, x, y, z);
if (is_calm_liquid(tile)) {
can_destroy = false;
}
}
// Call Original Method
(*Minecraft_handleMouseDown)(minecraft, param_1, can_destroy);
}
// Custom Crafting Recipes
static void Recipes_injection(unsigned char *recipes) {
// Add
Recipes_Type type1 = {
.item = 0,
.tile = 0,
.instance = {
.count = 3,
.id = 265,
.auxiliary = 0
},
.letter = '#'
};
ItemInstance result = {
.count = 1,
.id = (*(int32_t *) (bucket + Item_id_property_offset)),
.auxiliary = 0
};
(*Recipes_addShapedRecipe_2)(recipes, result, "# #", " # ", {type1});
}
// Custom Furnace Fuel
static int32_t FurnaceTileEntity_getBurnDuration_injection(ItemInstance const& item_instance) {
if (item_instance.count > 0 && item_instance.id == (*(int32_t *) (bucket + Item_id_property_offset)) && item_instance.auxiliary == (*(int32_t *) (*Tile_lava + Tile_id_property_offset))) {
return 20000;
} else {
// Call Original Method
return (*FurnaceTileEntity_getBurnDuration)(item_instance);
}
}
static void FurnaceTileEntity_tick_ItemInstance_setNull_injection(ItemInstance *item_instance) {
// Replace Lava Bucket With Empty Bucket When It Burns Out
if (item_instance->id == (*(int32_t *) (bucket + Item_id_property_offset))) {
item_instance->auxiliary = 0;
} else {
// Original Behavior
item_instance->count = 0;
item_instance->id = 0;
item_instance->auxiliary = 0;
}
}
// Init
void init_bucket() {
// Add Buckets
if (feature_has("Add Buckets", server_enabled)) {
// Add Items
misc_run_on_items_setup(Item_initItems_injection);
// Change Max Stack Size Based On Auxiliary
overwrite_calls((void *) ItemInstance_getMaxStackSize, (void *) ItemInstance_getMaxStackSize_injection);
// Creative Inventory
misc_run_on_creative_inventory_setup(Inventory_setupDefault_FillingContainer_addItem_call_injection);
// Make Liquids Selectable
overwrite_call((void *) 0x7f5b0, (void *) Mob_pick_Level_clip_injection);
misc_run_on_tick(handle_tick);
// Prevent Breaking Liquid
overwrite_calls((void *) Minecraft_handleMouseDown, (void *) Minecraft_handleMouseDown_injection);
// Custom Crafting Recipes
misc_run_on_recipes_setup(Recipes_injection);
// Custom Furnace Fuel
overwrite_calls((void *) FurnaceTileEntity_getBurnDuration, (void *) FurnaceTileEntity_getBurnDuration_injection);
overwrite_call((void *) 0xd351c, (void *) FurnaceTileEntity_tick_ItemInstance_setNull_injection);
}
}

View File

@ -16,10 +16,7 @@ static void inventory_add_item(unsigned char *inventory, unsigned char *item, bo
}
// Expand Creative Inventory
static int32_t Inventory_setupDefault_FillingContainer_addItem_call_injection(unsigned char *filling_container, ItemInstance *item_instance) {
// Call Original Method
int32_t ret = (*FillingContainer_addItem)(filling_container, item_instance);
static void Inventory_setupDefault_FillingContainer_addItem_call_injection(unsigned char *filling_container) {
// Add Items
inventory_add_item(filling_container, *Item_flintAndSteel, false);
inventory_add_item(filling_container, *Item_snowball, false);
@ -79,8 +76,6 @@ static int32_t Inventory_setupDefault_FillingContainer_addItem_call_injection(un
new_item_instance = (*ItemInstance_constructor_tile_extra)(new_item_instance, *Tile_stoneSlab, 1, 6);
(*FillingContainer_addItem)(filling_container, new_item_instance);
}
return ret;
}
#endif
@ -111,7 +106,7 @@ void init_creative() {
// Add Extra Items To Creative Inventory (Only Replace Specific Function Call)
if (feature_has("Expand Creative Inventory", server_enabled)) {
#ifndef MCPI_SERVER_MODE
overwrite_call((void *) 0x8e0fc, (void *) Inventory_setupDefault_FillingContainer_addItem_call_injection);
misc_run_on_creative_inventory_setup(Inventory_setupDefault_FillingContainer_addItem_call_injection);
#endif
// Use AuxDataTileItem by default instead of TileItem, so tiles in the Creative

View File

@ -27,6 +27,7 @@ __attribute__((constructor)) static void init() {
init_death();
init_options();
init_chat();
init_bucket();
init_home();
#ifndef MCPI_SERVER_MODE
init_benchmark();

View File

@ -5,6 +5,7 @@
#include <mods/input/input.h>
#include <mods/feature/feature.h>
#include <mods/creative/creative.h>
#include <mods/misc/misc.h>
// Enable Item Dropping
static int enable_drop = 0;
@ -29,8 +30,8 @@ static void _handle_drop(unsigned char *minecraft) {
unsigned char *player = *(unsigned char **) (minecraft + Minecraft_player_property_offset);
if (player != NULL) {
// Get Selected Slot
int32_t selected_slot = misc_get_real_selected_slot(player);
unsigned char *inventory = *(unsigned char **) (player + Player_inventory_property_offset);
int32_t selected_slot = *(int32_t *) (inventory + Inventory_selectedSlot_property_offset);
// Prepare
unsigned char *player_vtable = *(unsigned char **) player;
@ -38,13 +39,6 @@ static void _handle_drop(unsigned char *minecraft) {
unsigned char *inventory_vtable = *(unsigned char **) inventory;
FillingContainer_getItem_t FillingContainer_getItem = *(FillingContainer_getItem_t *) (inventory_vtable + FillingContainer_getItem_vtable_offset);
// Linked Slots
int32_t linked_slots_length = *(int32_t *) (inventory + FillingContainer_linked_slots_length_property_offset);
if (selected_slot < linked_slots_length) {
int32_t *linked_slots = *(int32_t **) (inventory + FillingContainer_linked_slots_property_offset);
selected_slot = linked_slots[selected_slot];
}
// Get Item
ItemInstance *inventory_item = (*FillingContainer_getItem)(inventory, selected_slot);
// Check

View File

@ -6,88 +6,103 @@
#include <mods/misc/misc.h>
#include "misc-internal.h"
// Callbacks
#define SETUP_CALLBACK(name) \
static std::vector<misc_update_function_t> &get_misc_##name##_functions() { \
static std::vector<misc_update_function_t> functions; \
return functions; \
} \
static void handle_misc_##name(unsigned char *obj) { \
for (misc_update_function_t function : get_misc_##name##_functions()) { \
(*function)(obj); \
} \
} \
void misc_run_on_##name(misc_update_function_t function) { \
get_misc_##name##_functions().push_back(function); \
}
// 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);
}
SETUP_CALLBACK(update);
// 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);
}
handle_misc_update(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);
}
SETUP_CALLBACK(tick);
// 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);
}
handle_misc_tick(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);
}
SETUP_CALLBACK(recipes_setup);
// 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);
}
handle_misc_recipes_setup(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);
}
SETUP_CALLBACK(furnace_recipes_setup);
// 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);
}
handle_misc_furnace_recipes_setup(recipes);
// Return
return recipes;
}
// Run Functions On Creative Inventory Setup
SETUP_CALLBACK(creative_inventory_setup);
// Handle Custom Creative Inventory Setup Behavior
static void Inventory_setupDefault_FillingContainer_addItem_call_injection(unsigned char *filling_container, ItemInstance *item_instance) {
// Call Original Method
(*FillingContainer_addItem)(filling_container, item_instance);
// Run Functions
handle_misc_creative_inventory_setup(filling_container);
}
// Run Functions On Tiles Setup
SETUP_CALLBACK(tiles_setup);
// Handle Custom Tiles Setup Behavior
static void Tile_initTiles_injection() {
// Run Functions
handle_misc_tiles_setup(NULL);
// Call Original Method
(*Tile_initTiles)();
}
// Run Functions On Items Setup
SETUP_CALLBACK(items_setup);
// Handle Custom Items Setup Behavior
static void Item_initItems_injection() {
// Run Functions
handle_misc_items_setup(NULL);
// Call Original Method
(*Item_initItems)();
}
// Init
void _init_misc_api() {
// Handle Custom Update Behavior
@ -97,4 +112,9 @@ void _init_misc_api() {
// Handle Custom Recipe Setup Behavior
overwrite_calls((void *) Recipes, (void *) Recipes_injection);
overwrite_calls((void *) FurnaceRecipes, (void *) FurnaceRecipes_injection);
// Handle Custom Creative Inventory Setup Behavior
overwrite_call((void *) 0x8e0fc, (void *) Inventory_setupDefault_FillingContainer_addItem_call_injection);
// Handle Custom Item/Tile Init Behavior
overwrite_calls((void *) Tile_initTiles, (void *) Tile_initTiles_injection);
overwrite_calls((void *) Item_initItems, (void *) Item_initItems_injection);
}

View File

@ -204,6 +204,23 @@ static void GameRenderer_render_injection(unsigned char *game_renderer, float pa
}
}
// Get Real Selected Slot
int32_t misc_get_real_selected_slot(unsigned char *player) {
// Get Selected Slot
unsigned char *inventory = *(unsigned char **) (player + Player_inventory_property_offset);
int32_t selected_slot = *(int32_t *) (inventory + Inventory_selectedSlot_property_offset);
// Linked Slots
int32_t linked_slots_length = *(int32_t *) (inventory + FillingContainer_linked_slots_length_property_offset);
if (selected_slot < linked_slots_length) {
int32_t *linked_slots = *(int32_t **) (inventory + FillingContainer_linked_slots_property_offset);
selected_slot = linked_slots[selected_slot];
}
// Return
return selected_slot;
}
// Init
static void nop() {
}

View File

@ -113,9 +113,9 @@ static void SoundEngine_init_injection(unsigned char *sound_engine, unsigned cha
void init_sound() {
// Implement Sound Engine
if (feature_has("Implement Sound Engine", server_disabled)) {
overwrite_calls((void *) SoundEngine_playUI, (void *) SoundEngine_playUI_injection);
overwrite_calls((void *) SoundEngine_play, (void *) SoundEngine_play_injection);
overwrite_calls((void *) SoundEngine_update, (void *) SoundEngine_update_injection);
overwrite((void *) SoundEngine_playUI, (void *) SoundEngine_playUI_injection);
overwrite((void *) SoundEngine_play, (void *) SoundEngine_play_injection);
overwrite((void *) SoundEngine_update, (void *) SoundEngine_update_injection);
overwrite_calls((void *) SoundEngine_init, (void *) SoundEngine_init_injection);
}
}

View File

@ -184,6 +184,9 @@ static Minecraft_getCreator_t Minecraft_getCreator = (Minecraft_getCreator_t) 0x
typedef unsigned char *(*Minecraft_getLevelSource_t)(unsigned char *minecraft);
static Minecraft_getLevelSource_t Minecraft_getLevelSource = (Minecraft_getLevelSource_t) 0x16e84;
typedef void (*Minecraft_handleMouseDown_t)(unsigned char *minecraft, int param_1, bool can_destroy);
static Minecraft_handleMouseDown_t Minecraft_handleMouseDown = (Minecraft_handleMouseDown_t) 0x1584c;
static uint32_t Minecraft_screen_width_property_offset = 0x20; // int32_t
static uint32_t Minecraft_network_handler_property_offset = 0x174; // NetEventCallback *
static uint32_t Minecraft_rak_net_instance_property_offset = 0x170; // RakNetInstance *
@ -199,6 +202,9 @@ static uint32_t Minecraft_screen_property_offset = 0xc10; // Screen *
static uint32_t Minecraft_gui_property_offset = 0x198; // Gui
static uint32_t Minecraft_pov_property_offset = 0x150; // Mob *
static uint32_t Minecraft_perf_renderer_property_offset = 0xcbc; // PerfRenderer *
static uint32_t Minecraft_targeted_x_property_offset = 0xc3c; // int32_t
static uint32_t Minecraft_targeted_y_property_offset = 0xc40; // int32_t
static uint32_t Minecraft_targeted_z_property_offset = 0xc44; // int32_t
// GameRenderer
@ -291,25 +297,6 @@ typedef int32_t (*MouseBuildInput_tickBuild_t)(unsigned char *mouse_build_input,
static MouseBuildInput_tickBuild_t MouseBuildInput_tickBuild = (MouseBuildInput_tickBuild_t) 0x17c98;
static void *MouseBuildInput_tickBuild_vtable_addr = (void *) 0x102564;
// Item
static uint32_t Item_is_stacked_by_data_property_offset = 0x19; // unsigned char / bool
static uint32_t Item_category_property_offset = 0x10; // int32_t
static uint32_t Item_max_damage_property_offset = 0x8; // int32_t
// TileItem
typedef unsigned char *(*TileItem_t)(unsigned char *tile_item, int32_t id);
static TileItem_t TileItem = (TileItem_t) 0xce3a4;
// AuxDataTileItem
#define AUX_DATA_TILE_ITEM_SIZE 0x2c
static unsigned char *AuxDataTileItem_vtable = (unsigned char *) 0x114a58;
static uint32_t AuxDataTileItem_icon_tile_property_offset = 0x28; // Tile *
// ItemInstance
typedef struct {
@ -326,6 +313,50 @@ typedef ItemInstance *(*ItemInstance_constructor_extra_t)(ItemInstance *item_ins
static ItemInstance_constructor_extra_t ItemInstance_constructor_tile_extra = (ItemInstance_constructor_extra_t) 0x99918;
static ItemInstance_constructor_extra_t ItemInstance_constructor_item_extra = (ItemInstance_constructor_extra_t) 0x99960;
typedef int32_t (*ItemInstance_getMaxStackSize_t)(ItemInstance *item_instance);
static ItemInstance_getMaxStackSize_t ItemInstance_getMaxStackSize = (ItemInstance_getMaxStackSize_t) 0x99ac8;
// Item
#define ITEM_SIZE 0x24
#define ITEM_VTABLE_SIZE 0x98
static unsigned char *Item_vtable = (unsigned char *) 0x10f128;
typedef void (*Item_initItems_t)();
static Item_initItems_t Item_initItems = (Item_initItems_t) 0x94ed0;
typedef unsigned char *(*Item_t)(unsigned char *item, int32_t id);
static Item_t Item = (Item_t) 0x99488;
typedef void (*Item_setIcon_t)(unsigned char *item, int32_t texture_x, int32_t texture_y);
static uint32_t Item_setIcon_vtable_offset = 0x18;
typedef int32_t (*Item_getIcon_t)(unsigned char *item, int32_t auxiliary);
static uint32_t Item_getIcon_vtable_offset = 0x14;
typedef int32_t (*Item_useOn_t)(unsigned char *item, ItemInstance *item_instance, unsigned char *player, unsigned char *level, int32_t x, int32_t y, int32_t z, int32_t hit_side, float hit_x, float hit_y, float hit_z);
static uint32_t Item_useOn_vtable_offset = 0x20;
static uint32_t Item_id_property_offset = 0x4; // int32_t
static uint32_t Item_is_stacked_by_data_property_offset = 0x19; // unsigned char / bool
static uint32_t Item_category_property_offset = 0x10; // int32_t
static uint32_t Item_max_damage_property_offset = 0x8; // int32_t
static uint32_t Item_max_stack_size_property_offset = 0x14; // int32_t
// TileItem
typedef unsigned char *(*TileItem_t)(unsigned char *tile_item, int32_t id);
static TileItem_t TileItem = (TileItem_t) 0xce3a4;
// AuxDataTileItem
#define AUX_DATA_TILE_ITEM_SIZE 0x2c
static unsigned char *AuxDataTileItem_vtable = (unsigned char *) 0x114a58;
static uint32_t AuxDataTileItem_icon_tile_property_offset = 0x28; // Tile *
// Entity
static uint32_t Entity_x_property_offset = 0x4; // float
@ -426,8 +457,22 @@ static Level_saveLevelData_t Level_saveLevelData = (Level_saveLevelData_t) 0xa2e
typedef void (*Level_setTileAndData_t)(unsigned char *level, int32_t x, int32_t y, int32_t z, int32_t id, int32_t data);
static Level_setTileAndData_t Level_setTileAndData = (Level_setTileAndData_t) 0xa38b4;
typedef int32_t (*Level_getTile_t)(unsigned char *level, int32_t x, int32_t y, int32_t z);
static Level_getTile_t Level_getTile = (Level_getTile_t) 0xa3380;
typedef unsigned char *(*Level_getMaterial_t)(unsigned char *level, int32_t x, int32_t y, int32_t z);
static Level_getMaterial_t Level_getMaterial = (Level_getMaterial_t) 0xa27f8;
typedef void (*Level_clip_t)(unsigned char *level, unsigned char *param_1, unsigned char *param_2, bool param_3, bool clip_liquids);
static Level_clip_t Level_clip = (Level_clip_t) 0xa3db0;
static uint32_t Level_players_property_offset = 0x60; // std::vector<ServerPlayer *>
// Material
typedef bool (*Material_isSolid_t)(unsigned char *material);
static uint32_t Material_isSolid_vtable_offset = 0x8;
// LevelRenderer
typedef void (*LevelRenderer_render_t)(unsigned char *level_renderer, unsigned char *mob, int param_1, float delta);
@ -557,7 +602,7 @@ static uint32_t Touch_SelectWorldScreen_world_created_property_offset = 0x151; /
// FillingContainer
typedef int32_t (*FillingContainer_addItem_t)(unsigned char *filling_container, ItemInstance *item_instance);
typedef void (*FillingContainer_addItem_t)(unsigned char *filling_container, ItemInstance *item_instance);
static FillingContainer_addItem_t FillingContainer_addItem = (FillingContainer_addItem_t) 0x92aa0;
typedef ItemInstance *(*FillingContainer_getItem_t)(unsigned char *filling_container, int32_t slot);
@ -566,6 +611,9 @@ static uint32_t FillingContainer_getItem_vtable_offset = 0x8;
typedef void (*FillingContainer_setItem_t)(unsigned char *filling_container, int32_t slot, ItemInstance *item_instance);
static uint32_t FillingContainer_setItem_vtable_offset = 0xc;
typedef bool (*FillingContainer_add_t)(unsigned char *filling_container, ItemInstance *item_instance);
static uint32_t FillingContainer_add_vtable_offset = 0x30;
typedef void (*FillingContainer_clearSlot_t)(unsigned char *filling_container, int32_t slot);
static FillingContainer_clearSlot_t FillingContainer_clearSlot = (FillingContainer_clearSlot_t) 0x922f8;
@ -766,6 +814,14 @@ struct ConnectedClient {
typedef unsigned char *(*Tile_setDescriptionId_t)(unsigned char *tile, std::string const& description_id);
static uint32_t Tile_setDescriptionId_vtable_offset = 0xe0;
// Item
typedef void (*Item_setDescriptionId_t)(unsigned char *item, std::string const& name);
static uint32_t Item_setDescriptionId_vtable_offset = 0x6c;
typedef std::string (*Item_getDescriptionId_t)(unsigned char *item, const ItemInstance *item_instance);
static uint32_t Item_getDescriptionId_vtable_offset = 0x7c;
// AppPlatform
typedef void (*AppPlatform_saveScreenshot_t)(unsigned char *app_platform, std::string const& path, int32_t width, int32_t height);
@ -870,14 +926,28 @@ static Textures_loadAndBindTexture_t Textures_loadAndBindTexture = (Textures_loa
// Recipes
typedef void (*Recipes_addShapelessRecipe_t)(unsigned char *recipes, ItemInstance const& result, std::vector<Recipes_Type> const& param_2);
typedef void (*Recipes_addShapelessRecipe_t)(unsigned char *recipes, ItemInstance const& result, std::vector<Recipes_Type> const& ingredients);
static Recipes_addShapelessRecipe_t Recipes_addShapelessRecipe = (Recipes_addShapelessRecipe_t) 0x9c3dc;
typedef void (*Recipes_addShapedRecipe_1_t)(unsigned char *recipes, ItemInstance const& result, std::string const& line_1, std::vector<Recipes_Type> const& ingredients);
static Recipes_addShapedRecipe_1_t Recipes_addShapedRecipe_1 = (Recipes_addShapedRecipe_1_t) 0x9ca74;
typedef void (*Recipes_addShapedRecipe_2_t)(unsigned char *recipes, ItemInstance const& result, std::string const& line_1, std::string const& line_2, std::vector<Recipes_Type> const& ingredients);
static Recipes_addShapedRecipe_2_t Recipes_addShapedRecipe_2 = (Recipes_addShapedRecipe_2_t) 0x9ca24;
typedef void (*Recipes_addShapedRecipe_3_t)(unsigned char *recipes, ItemInstance const& result, std::string const& line_1, std::string const& line_2, std::string const& line_3, std::vector<Recipes_Type> const& ingredients);
static Recipes_addShapedRecipe_3_t Recipes_addShapedRecipe_3 = (Recipes_addShapedRecipe_3_t) 0x9c9d0;
// 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;
// FurnaceTileEntity
typedef int32_t (*FurnaceTileEntity_getBurnDuration_t)(ItemInstance const& item_instance);
static FurnaceTileEntity_getBurnDuration_t FurnaceTileEntity_getBurnDuration = (FurnaceTileEntity_getBurnDuration_t) 0xd33f8;
#endif
#pragma GCC diagnostic pop