diff --git a/dependencies/symbol-processor/src b/dependencies/symbol-processor/src index 225eb25..67c4ada 160000 --- a/dependencies/symbol-processor/src +++ b/dependencies/symbol-processor/src @@ -1 +1 @@ -Subproject commit 225eb259fe00348044b7b9008a810204004701df +Subproject commit 67c4adaa772445f919f37131d7605bd374c67845 diff --git a/libreborn/include/libreborn/patch.h b/libreborn/include/libreborn/patch.h index 38b6d82..63e617c 100644 --- a/libreborn/include/libreborn/patch.h +++ b/libreborn/include/libreborn/patch.h @@ -11,24 +11,53 @@ extern "C" { void reborn_init_patch(); void _overwrite_call(const char *file, int line, void *start, void *target); -#define overwrite_call(start, target) _overwrite_call(__FILE__, __LINE__, start, target); +#define overwrite_call(start, target) _overwrite_call(__FILE__, __LINE__, start, target) + +#define _setup_fancy_overwrite(start, name, target) \ + if (!_is_new_method_##name()) { \ + ERR("Method Is Not \"New\""); \ + } \ + static name##_t _original_for_##target = start; \ + static name##_t _helper_for_##target = _overwrite_helper_for_##name(target, _original_for_##target) + +#define _update_references(from, to) \ + { \ + void *old_reference = (void *) from; \ + for (int i = 0; _all_method_symbols[i] != nullptr; i++) { \ + if (_all_method_symbols[i] == old_reference) { \ + _all_method_symbols[i] = (void *) to; \ + } \ + } \ + } void _overwrite_calls(const char *file, int line, void *start, void *target); -#define overwrite_calls(start, target) _overwrite_calls(__FILE__, __LINE__, start, target); +#define overwrite_calls_manual(start, target) _overwrite_calls(__FILE__, __LINE__, start, target) +#define overwrite_calls(start, target) \ + { \ + _setup_fancy_overwrite(start, start, target); \ + overwrite_calls_manual((void *) start, (void *) _helper_for_##target); \ + _update_references(start, _helper_for_##target); \ + } + +#define overwrite_virtual_calls(start, target) \ + { \ + _setup_fancy_overwrite(*start##_vtable_addr, start, target); \ + overwrite_calls_manual((void *) *start##_vtable_addr, (void *) _helper_for_##target); \ + } void _overwrite_calls_within(const char *file, int line, void *from, void *to, void *start, void *target); -#define overwrite_calls_within(from, to, start, target) _overwrite_calls_within(__FILE__, __LINE__, from, to, start, target); +#define overwrite_calls_within(from, to, start, target) _overwrite_calls_within(__FILE__, __LINE__, from, to, start, target) void *extract_from_bl_instruction(unsigned char *from); void _overwrite(const char *file, int line, void *start, void *target); -#define overwrite(start, target) _overwrite(__FILE__, __LINE__, start, target); +#define overwrite(start, target) _overwrite(__FILE__, __LINE__, (void *) start, (void *) target) void _patch(const char *file, int line, void *start, unsigned char patch[4]); -#define patch(start, patch) _patch(__FILE__, __LINE__, start, patch); +#define patch(start, patch) _patch(__FILE__, __LINE__, start, patch) void _patch_address(const char *file, int line, void *start, void *target); -#define patch_address(start, target) _patch_address(__FILE__, __LINE__, start, target); +#define patch_address(start, target) _patch_address(__FILE__, __LINE__, (void *) start, (void *) target) #endif diff --git a/libreborn/include/libreborn/util.h b/libreborn/include/libreborn/util.h index 707fdf0..d4960a7 100644 --- a/libreborn/include/libreborn/util.h +++ b/libreborn/include/libreborn/util.h @@ -16,6 +16,11 @@ } // Hook Library Function +#ifdef __cplusplus +#define hooked_function_setup extern "C" +#else +#define hooked_function_setup +#endif #define HOOK(name, return_type, args) \ typedef return_type (*name##_t)args; \ static name##_t real_##name = NULL; \ @@ -30,7 +35,7 @@ } \ } \ \ - __attribute__((__used__)) return_type name args + hooked_function_setup __attribute__((__used__)) return_type name args #ifdef __cplusplus extern "C" { diff --git a/mods/CMakeLists.txt b/mods/CMakeLists.txt index 358e161..46a4268 100644 --- a/mods/CMakeLists.txt +++ b/mods/CMakeLists.txt @@ -3,14 +3,14 @@ project(mods) # Common Sources set(SRC # compat - src/compat/compat.c - src/compat/egl.c - src/compat/x11.c - src/compat/bcm_host.c + src/compat/compat.cpp + src/compat/egl.cpp + src/compat/x11.cpp + src/compat/bcm_host.cpp # readdir - src/readdir/readdir.c + src/readdir/readdir.cpp # feature - src/feature/feature.c + src/feature/feature.cpp # version src/version/version.cpp # chat @@ -19,30 +19,28 @@ set(SRC # creative src/creative/creative.cpp # game-mode - src/game-mode/game-mode.c + src/game-mode/game-mode.cpp src/game-mode/ui.cpp # override - src/override/override.c + src/override/override.cpp # death src/death/death.cpp # misc - src/misc/misc.c src/misc/misc.cpp src/misc/logging.cpp src/misc/api.cpp # options - src/options/options.c src/options/options.cpp # bucket src/bucket/bucket.cpp # cake src/cake/cake.cpp # home - src/home/home.c + src/home/home.cpp # test - src/test/test.c + src/test/test.cpp # init - src/init/init.c + src/init/init.cpp ) # Server-Only Sources @@ -76,10 +74,10 @@ else() src/camera/camera.cpp # input src/input/input.cpp - src/input/bow.c - src/input/attack.c - src/input/toggle.c - src/input/misc.c + src/input/bow.cpp + src/input/attack.cpp + src/input/toggle.cpp + src/input/misc.cpp src/input/drop.cpp src/input/crafting.cpp # sign @@ -95,7 +93,7 @@ else() src/skin/skin.cpp src/skin/loader.cpp # screenshot - src/screenshot/screenshot.c + src/screenshot/screenshot.cpp # textures src/textures/textures.cpp src/textures/lava.cpp diff --git a/mods/include/mods/bucket/bucket.h b/mods/include/mods/bucket/bucket.h index 54f34e1..fb141e8 100644 --- a/mods/include/mods/bucket/bucket.h +++ b/mods/include/mods/bucket/bucket.h @@ -2,12 +2,4 @@ #include -#ifdef __cplusplus -extern "C" { -#endif - extern bool buckets_enabled; - -#ifdef __cplusplus -} -#endif diff --git a/mods/include/mods/chat/chat.h b/mods/include/mods/chat/chat.h index f8a1001..8fb3c45 100644 --- a/mods/include/mods/chat/chat.h +++ b/mods/include/mods/chat/chat.h @@ -1,22 +1,13 @@ #pragma once +#include + #include #include -#ifdef __cplusplus -#include // Send API Command std::string chat_send_api_command(Minecraft *minecraft, std::string str); -#endif - -#ifdef __cplusplus -extern "C" { -#endif // Override using the HOOK() macro to provide customized chat behavior. void chat_send_message(ServerSideNetworkHandler *server_side_network_handler, char *username, char *message); void chat_handle_packet_send(Minecraft *minecraft, ChatPacket *packet); - -#ifdef __cplusplus -} -#endif diff --git a/mods/include/mods/compat/compat.h b/mods/include/mods/compat/compat.h index 0d1150d..c307bc7 100644 --- a/mods/include/mods/compat/compat.h +++ b/mods/include/mods/compat/compat.h @@ -1,12 +1,4 @@ #pragma once -#ifdef __cplusplus -extern "C" { -#endif - int compat_check_exit_requested(); void compat_request_exit(); - -#ifdef __cplusplus -} -#endif diff --git a/mods/include/mods/creative/creative.h b/mods/include/mods/creative/creative.h index 84a353e..2b6f63e 100644 --- a/mods/include/mods/creative/creative.h +++ b/mods/include/mods/creative/creative.h @@ -1,11 +1,3 @@ #pragma once -#ifdef __cplusplus -extern "C" { -#endif - -int creative_is_restricted(); - -#ifdef __cplusplus -} -#endif +int creative_is_restricted(); \ No newline at end of file diff --git a/mods/include/mods/feature/feature.h b/mods/include/mods/feature/feature.h index cbd1fec..7eea3ff 100644 --- a/mods/include/mods/feature/feature.h +++ b/mods/include/mods/feature/feature.h @@ -2,11 +2,7 @@ #include -#ifdef __cplusplus -extern "C" { -#endif - -int _feature_has(const char *name); +bool _feature_has(const char *name); #ifdef MCPI_SERVER_MODE #define _feature_has__server_defaul_is_server_disabled(name) 0 @@ -16,7 +12,3 @@ int _feature_has(const char *name); #else #define feature_has(name, server_default) _feature_has(name) #endif - -#ifdef __cplusplus -} -#endif diff --git a/mods/include/mods/fps/fps.h b/mods/include/mods/fps/fps.h index 237871a..702a344 100644 --- a/mods/include/mods/fps/fps.h +++ b/mods/include/mods/fps/fps.h @@ -1,11 +1,3 @@ #pragma once -#ifdef __cplusplus -extern "C" { -#endif - extern double fps; - -#ifdef __cplusplus -} -#endif diff --git a/mods/include/mods/home/home.h b/mods/include/mods/home/home.h index 8a3462b..585163a 100644 --- a/mods/include/mods/home/home.h +++ b/mods/include/mods/home/home.h @@ -1,11 +1,3 @@ #pragma once -#ifdef __cplusplus -extern "C" { -#endif - char *home_get(); - -#ifdef __cplusplus -} -#endif diff --git a/mods/include/mods/init/init.h b/mods/include/mods/init/init.h index 6dce44d..288bebc 100644 --- a/mods/include/mods/init/init.h +++ b/mods/include/mods/init/init.h @@ -2,10 +2,6 @@ #include -#ifdef __cplusplus -extern "C" { -#endif - void run_tests(); void init_version(); void init_compat(); @@ -35,8 +31,4 @@ void init_options(); void init_chat(); void init_bucket(); void init_cake(); -void init_home(); - -#ifdef __cplusplus -} -#endif +void init_home(); \ No newline at end of file diff --git a/mods/include/mods/input/input.h b/mods/include/mods/input/input.h index 78b1a4b..50f98f4 100644 --- a/mods/include/mods/input/input.h +++ b/mods/include/mods/input/input.h @@ -2,10 +2,6 @@ #include -#ifdef __cplusplus -extern "C" { -#endif - typedef void (*input_tick_function_t)(Minecraft *minecraft); void input_run_on_tick(input_tick_function_t function); @@ -17,7 +13,3 @@ void input_open_crafting(); void input_set_is_left_click(int val); void input_set_mouse_grab_state(int state); - -#ifdef __cplusplus -} -#endif diff --git a/mods/include/mods/misc/misc.h b/mods/include/mods/misc/misc.h index 493d270..e9d6587 100644 --- a/mods/include/mods/misc/misc.h +++ b/mods/include/mods/misc/misc.h @@ -1,13 +1,9 @@ #pragma once -#include +#include #include -#ifdef __cplusplus -extern "C" { -#endif - int32_t misc_get_real_selected_slot(Player *player); typedef void (*misc_update_function_Minecraft_t)(Minecraft *obj); @@ -26,13 +22,4 @@ void misc_run_on_language_setup(misc_update_function_void_t function); // obj == typedef bool (*misc_update_function_key_press_t)(Minecraft *minecrtaft, int key); void misc_run_on_game_key_press(misc_update_function_key_press_t function); // In-Game Key Presses Only -void Level_saveLevelData_injection(Level *level); - -// Use this instead of directly calling Gui::addMessage(), it has proper logging! -void misc_add_message(Gui *gui, const char *text); - extern bool is_in_chat; - -#ifdef __cplusplus -} -#endif diff --git a/mods/include/mods/override/override.h b/mods/include/mods/override/override.h index 331ec46..dcd39aa 100644 --- a/mods/include/mods/override/override.h +++ b/mods/include/mods/override/override.h @@ -1,11 +1,3 @@ #pragma once -#ifdef __cplusplus -extern "C" { -#endif - char *override_get_path(const char *filename); - -#ifdef __cplusplus -} -#endif diff --git a/mods/include/mods/screenshot/screenshot.h b/mods/include/mods/screenshot/screenshot.h index e72cb03..f0e063d 100644 --- a/mods/include/mods/screenshot/screenshot.h +++ b/mods/include/mods/screenshot/screenshot.h @@ -1,11 +1,3 @@ #pragma once -#ifdef __cplusplus -extern "C" { -#endif - void screenshot_take(char *home); - -#ifdef __cplusplus -} -#endif diff --git a/mods/include/mods/sign/sign.h b/mods/include/mods/sign/sign.h index fd65431..de0a4d4 100644 --- a/mods/include/mods/sign/sign.h +++ b/mods/include/mods/sign/sign.h @@ -1,11 +1,3 @@ #pragma once -#ifdef __cplusplus -extern "C" { -#endif - -void sign_key_press(char key); - -#ifdef __cplusplus -} -#endif +void sign_key_press(char key); \ No newline at end of file diff --git a/mods/include/mods/textures/textures.h b/mods/include/mods/textures/textures.h index 3b6e714..202a4fe 100644 --- a/mods/include/mods/textures/textures.h +++ b/mods/include/mods/textures/textures.h @@ -2,12 +2,4 @@ #include -#ifdef __cplusplus -extern "C" { -#endif - void glTexSubImage2D_with_scaling(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLsizei normal_texture_width, GLsizei normal_texture_height, GLenum format, GLenum type, const void *pixels); - -#ifdef __cplusplus -} -#endif diff --git a/mods/include/mods/title-screen/title-screen.h b/mods/include/mods/title-screen/title-screen.h index cf6330d..bbe30a4 100644 --- a/mods/include/mods/title-screen/title-screen.h +++ b/mods/include/mods/title-screen/title-screen.h @@ -3,6 +3,4 @@ #include #include -extern "C" { void title_screen_load_splashes(std::vector &splashes); -} diff --git a/mods/include/mods/version/version.h b/mods/include/mods/version/version.h index dd909f0..27c1aaa 100644 --- a/mods/include/mods/version/version.h +++ b/mods/include/mods/version/version.h @@ -1,11 +1,3 @@ #pragma once -#ifdef __cplusplus -extern "C" { -#endif - char *version_get(); - -#ifdef __cplusplus -} -#endif diff --git a/mods/src/atlas/atlas.cpp b/mods/src/atlas/atlas.cpp index 4c4b13d..a169a8f 100644 --- a/mods/src/atlas/atlas.cpp +++ b/mods/src/atlas/atlas.cpp @@ -7,13 +7,13 @@ #include // Fix Grass And Leaves Inventory Rendering When The gui_blocks Atlas Is Disabled -static void ItemRenderer_renderGuiItemCorrect_injection(Font *font, Textures *textures, ItemInstance *item_instance, int32_t param_1, int32_t param_2) { +static void ItemRenderer_renderGuiItemCorrect_injection(ItemRenderer_renderGuiItemCorrect_t original, Font *font, Textures *textures, ItemInstance *item_instance, int32_t param_1, int32_t param_2) { int32_t leaves_id = Tile_leaves->id; int32_t grass_id = Tile_grass->id; // Replace Rendered Item With Carried Variant ItemInstance carried_item_instance; bool use_carried = false; - if (item_instance != NULL) { + if (item_instance != nullptr) { if (item_instance->id == leaves_id) { ItemInstance_constructor_tile_extra(&carried_item_instance, Tile_leaves_carried, item_instance->count, item_instance->auxiliary); use_carried = true; @@ -28,7 +28,7 @@ static void ItemRenderer_renderGuiItemCorrect_injection(Font *font, Textures *te glDisable(GL_DEPTH_TEST); // Call Original Method - ItemRenderer_renderGuiItemCorrect(font, textures, use_carried ? &carried_item_instance : item_instance, param_1, param_2); + original(font, textures, use_carried ? &carried_item_instance : item_instance, param_1, param_2); // Revert GL State Changes if (depth_test_was_enabled) { @@ -40,7 +40,7 @@ static void ItemRenderer_renderGuiItemCorrect_injection(Font *font, Textures *te static int item_color_fix_mode = 0; #define POTENTIAL_FURNACE_ITEM_TRANSPARENCY 0x33 #define INVALID_FURNACE_ITEM_MULTIPLIER 0.25f -static void Tesselator_color_injection(Tesselator *tesselator, int32_t r, int32_t g, int32_t b, int32_t a) { +static void Tesselator_color_injection(Tesselator_color_t original, Tesselator *tesselator, int32_t r, int32_t g, int32_t b, int32_t a) { // Fix Furnace UI if (item_color_fix_mode != 0) { // Force Translucent @@ -55,16 +55,16 @@ static void Tesselator_color_injection(Tesselator *tesselator, int32_t r, int32_ } // Call Original Method - Tesselator_color(tesselator, r, g, b, a); + original(tesselator, r, g, b, a); } -static void Tesselator_begin_injection(Tesselator *tesselator, int32_t mode) { +static void Tesselator_begin_injection(Tesselator_begin_t original, Tesselator *tesselator, int32_t mode) { // Call Original Method - Tesselator_begin(tesselator, mode); + original(tesselator, mode); // Fix Furnace UI if (item_color_fix_mode != 0) { // Implict Translucent - Tesselator_color_injection(tesselator, 0xff, 0xff, 0xff, 0xff); + Tesselator_color(tesselator, 0xff, 0xff, 0xff, 0xff); } } static void InventoryPane_renderBatch_Tesselator_color_injection(Tesselator *tesselator, int32_t r, int32_t g, int32_t b) { @@ -74,9 +74,9 @@ static void InventoryPane_renderBatch_Tesselator_color_injection(Tesselator *tes // Enable Item Color Fix item_color_fix_mode = 2; } -static void ItemRenderer_renderGuiItem_two_injection(Font *font, Textures *textures, ItemInstance *item_instance, float param_1, float param_2, float param_3, float param_4, bool param_5) { +static void ItemRenderer_renderGuiItem_two_injection(ItemRenderer_renderGuiItem_two_t original, Font *font, Textures *textures, ItemInstance *item_instance, float param_1, float param_2, float param_3, float param_4, bool param_5) { // Call Original Method - ItemRenderer_renderGuiItem_two(font, textures, item_instance, param_1, param_2, param_3, param_4, param_5); + original(font, textures, item_instance, param_1, param_2, param_3, param_4, param_5); // Disable Item Color Fix item_color_fix_mode = 0; @@ -91,18 +91,18 @@ static void FurnaceScreen_render_ItemRenderer_renderGuiItem_one_injection(Font * // Init void init_atlas() { - // Add Better NULL-Check (And More UI Fixes When The gui_blocks Atlas Is Disabled) - overwrite_calls((void *) ItemRenderer_renderGuiItem_two, (void *) ItemRenderer_renderGuiItem_two_injection); + // Add Better nullptr-Check (And More UI Fixes When The gui_blocks Atlas Is Disabled) + overwrite_calls(ItemRenderer_renderGuiItem_two, ItemRenderer_renderGuiItem_two_injection); // Disable The gui_blocks Atlas Which Contains Pre-Rendered Textures For Blocks In The Inventory if (feature_has("Disable \"gui_blocks\" Atlas", server_disabled)) { unsigned char disable_gui_blocks_atlas_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop" patch((void *) 0x63c2c, disable_gui_blocks_atlas_patch); // Fix Grass And Leaves Inventory Rendering When The gui_blocks Atlas Is Disabled - overwrite_calls((void *) ItemRenderer_renderGuiItemCorrect, (void *) ItemRenderer_renderGuiItemCorrect_injection); + overwrite_calls(ItemRenderer_renderGuiItemCorrect, ItemRenderer_renderGuiItemCorrect_injection); // Fix Furnace UI - overwrite_calls((void *) Tesselator_begin, (void *) Tesselator_begin_injection); - overwrite_calls((void *) Tesselator_color, (void *) Tesselator_color_injection); + overwrite_calls(Tesselator_begin, Tesselator_begin_injection); + overwrite_calls(Tesselator_color, Tesselator_color_injection); overwrite_call((void *) 0x32324, (void *) FurnaceScreen_render_ItemRenderer_renderGuiItem_one_injection); overwrite_call((void *) 0x1e21c, (void *) InventoryPane_renderBatch_Tesselator_color_injection); } diff --git a/mods/src/benchmark/benchmark.cpp b/mods/src/benchmark/benchmark.cpp index 3c708c4..aae2bab 100644 --- a/mods/src/benchmark/benchmark.cpp +++ b/mods/src/benchmark/benchmark.cpp @@ -64,7 +64,7 @@ static void Minecraft_tick_injection(__attribute__((unused)) Minecraft *minecraf // Get Time static long long int get_time() { - struct timespec ts; + timespec ts = {}; clock_gettime(CLOCK_MONOTONIC_RAW, &ts); long long int a = (long long int) ts.tv_nsec; long long int b = ((long long int) ts.tv_sec) * NANOSECONDS_IN_SECOND; diff --git a/mods/src/bucket/bucket.cpp b/mods/src/bucket/bucket.cpp index b2fa766..41d1843 100644 --- a/mods/src/bucket/bucket.cpp +++ b/mods/src/bucket/bucket.cpp @@ -7,7 +7,7 @@ #include // Items -static FoodItem *bucket = NULL; +static FoodItem *bucket = nullptr; // Description And Texture static std::string BucketItem_getDescriptionId(__attribute__((unused)) FoodItem *item, ItemInstance *item_instance) { @@ -111,7 +111,7 @@ static int32_t BucketItem_useOn(__attribute__((unused)) FoodItem *item, ItemInst // Get Current Tile bool valid = false; Material *material = level->vtable->getMaterial(level, x, y, z); - if (material != NULL) { + if (material != nullptr) { valid = !material->vtable->isSolid(material); } if (item_instance->auxiliary != Tile_water->id && item_instance->auxiliary != Tile_lava->id) { @@ -136,7 +136,7 @@ static int BucketItem_getUseDuration(__attribute__((unused)) FoodItem *item, Ite static ItemInstance BucketItem_useTimeDepleted(FoodItem *item, ItemInstance *item_instance, Level *level, Player *player) { if (item_instance->auxiliary == 1) { - *item_instance = FoodItem_useTimeDepleted_non_virtual(item, item_instance, level, player); + *item_instance = (*FoodItem_useTimeDepleted_vtable_addr)(item, item_instance, level, player); // Set it to a empty bucket item_instance->auxiliary = 0; item_instance->count = 1; @@ -161,7 +161,7 @@ static ItemInstance *BucketItem_use(FoodItem *item, ItemInstance *item_instance, static ItemInstance *BucketItem_getCraftingRemainingItem(FoodItem *item, ItemInstance *item_instance) { if (item_instance->auxiliary == 0) { - return NULL; + return nullptr; } ItemInstance *ret = alloc_ItemInstance(); ret->id = item->id; @@ -212,25 +212,25 @@ static void Item_initItems_injection(__attribute__((unused)) void *null) { } // Change Max Stack Size Based On Auxiliary -static int32_t ItemInstance_getMaxStackSize_injection(ItemInstance *item_instance) { +static int32_t ItemInstance_getMaxStackSize_injection(ItemInstance_getMaxStackSize_t original, ItemInstance *item_instance) { if (item_instance->id == bucket->id && item_instance->auxiliary == 0) { // Custom Value return 16; } else { // Call Original Method - return ItemInstance_getMaxStackSize(item_instance); + return original(item_instance); } } // Milking -bool Cow_interact_injection(Cow *self, Player *player) { +bool Cow_interact_injection(Cow_interact_t original, Cow *self, Player *player) { ItemInstance *item = Inventory_getSelected(player->inventory); if (item && item->id == bucket->id && item->auxiliary == 0) { // Fill with milk fill_bucket(item, player, 1); return true; } - return Cow_interact_non_virtual(self, player); + return original(self, player); } // Creative Inventory @@ -255,7 +255,7 @@ static HitResult Mob_pick_Level_clip_injection(Level *level, unsigned char *para } static void handle_tick(Minecraft *minecraft) { LocalPlayer *player = minecraft->player; - if (player != NULL) { + if (player != nullptr) { // Get Selected Slot int32_t selected_slot = misc_get_real_selected_slot((Player *) player); Inventory *inventory = player->inventory; @@ -263,7 +263,7 @@ static void handle_tick(Minecraft *minecraft) { // Get Item ItemInstance *inventory_item = inventory->vtable->getItem(inventory, selected_slot); // Check - is_holding_bucket = inventory_item != NULL && inventory_item->id == bucket->id && inventory_item->auxiliary == 0; + is_holding_bucket = inventory_item != nullptr && inventory_item->id == bucket->id && inventory_item->auxiliary == 0; } } @@ -277,10 +277,10 @@ static bool is_calm_liquid(int32_t id) { return false; } } -static void Minecraft_handleMouseDown_injection(Minecraft *minecraft, int param_1, bool can_destroy) { +static void Minecraft_handleMouseDown_injection(Minecraft_handleMouseDown_t original, Minecraft *minecraft, int param_1, bool can_destroy) { // Check Level *level = minecraft->level; - if (level != NULL) { + if (level != nullptr) { int32_t x = minecraft->hit_result.x; int32_t y = minecraft->hit_result.y; int32_t z = minecraft->hit_result.z; @@ -291,7 +291,7 @@ static void Minecraft_handleMouseDown_injection(Minecraft *minecraft, int param_ } // Call Original Method - Minecraft_handleMouseDown(minecraft, param_1, can_destroy); + original(minecraft, param_1, can_destroy); } // Custom Crafting Recipes @@ -319,12 +319,12 @@ static void Recipes_injection(Recipes *recipes) { } // Custom Furnace Fuel -static int32_t FurnaceTileEntity_getBurnDuration_injection(ItemInstance *item_instance) { +static int32_t FurnaceTileEntity_getBurnDuration_injection(FurnaceTileEntity_getBurnDuration_t original, ItemInstance *item_instance) { if (item_instance->count > 0 && item_instance->id == bucket->id && item_instance->auxiliary == Tile_lava->id) { return 20000; } else { // Call Original Method - return FurnaceTileEntity_getBurnDuration(item_instance); + return original(item_instance); } } static void FurnaceTileEntity_tick_ItemInstance_setNull_injection(ItemInstance *item_instance) { @@ -353,20 +353,20 @@ void init_bucket() { // 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); + overwrite_calls(ItemInstance_getMaxStackSize, ItemInstance_getMaxStackSize_injection); // Enable milking - patch_address((void *) Cow_interact_vtable_addr, (void *) Cow_interact_injection); + overwrite_virtual_calls(Cow_interact, Cow_interact_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); + overwrite_calls(Minecraft_handleMouseDown, 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_calls(FurnaceTileEntity_getBurnDuration, FurnaceTileEntity_getBurnDuration_injection); overwrite_call((void *) 0xd351c, (void *) FurnaceTileEntity_tick_ItemInstance_setNull_injection); // Language for milk misc_run_on_language_setup(Language_injection); diff --git a/mods/src/cake/cake.cpp b/mods/src/cake/cake.cpp index c9c0034..c7a85b1 100644 --- a/mods/src/cake/cake.cpp +++ b/mods/src/cake/cake.cpp @@ -6,7 +6,7 @@ #include #include -static Tile *cake = NULL; +static Tile *cake = nullptr; #define CAKE_LEN 0.0625F diff --git a/mods/src/camera/camera.cpp b/mods/src/camera/camera.cpp index af89237..59c3265 100644 --- a/mods/src/camera/camera.cpp +++ b/mods/src/camera/camera.cpp @@ -7,16 +7,16 @@ #include // Take Screenshot Using TripodCamera -static void AppPlatform_linux_saveScreenshot_injection(__attribute__((unused)) AppPlatform *app_platform, __attribute__((unused)) std::string const& path, __attribute__((unused)) int32_t width, __attribute__((unused)) int32_t height) { +static void AppPlatform_saveScreenshot_injection(__attribute__((unused)) AppPlatform_saveScreenshot_t original, __attribute__((unused)) AppPlatform *app_platform, __attribute__((unused)) std::string *path, __attribute__((unused)) int32_t width, __attribute__((unused)) int32_t height) { #ifndef MCPI_HEADLESS_MODE screenshot_take(home_get()); #endif } // Enable TripodCameraRenderer -static EntityRenderDispatcher *EntityRenderDispatcher_injection(EntityRenderDispatcher *dispatcher) { +static EntityRenderDispatcher *EntityRenderDispatcher_injection(EntityRenderDispatcher_constructor_t original, EntityRenderDispatcher *dispatcher) { // Call Original Method - EntityRenderDispatcher_constructor(dispatcher); + original(dispatcher); // Register TripodCameraRenderer TripodCameraRenderer *renderer = alloc_TripodCameraRenderer(); @@ -36,12 +36,12 @@ static void TripodCamera_tick_Level_addParticle_call_injection(Level *level, std // Init void init_camera() { // Implement AppPlatform_linux::saveScreenshot So Cameras Work - patch_address(AppPlatform_linux_saveScreenshot_vtable_addr, (void *) AppPlatform_linux_saveScreenshot_injection); + overwrite_virtual_calls(AppPlatform_saveScreenshot, AppPlatform_saveScreenshot_injection); // Fix Camera Rendering if (feature_has("Fix Camera Rendering", server_disabled)) { // Enable TripodCameraRenderer - overwrite_calls((void *) EntityRenderDispatcher_constructor, (void *) EntityRenderDispatcher_injection); + overwrite_calls(EntityRenderDispatcher_constructor, EntityRenderDispatcher_injection); // Display Smoke From TripodCamera Higher overwrite_call((void *) 0x87dc4, (void *) TripodCamera_tick_Level_addParticle_call_injection); } diff --git a/mods/src/chat/chat.cpp b/mods/src/chat/chat.cpp index 857e1eb..66d6266 100644 --- a/mods/src/chat/chat.cpp +++ b/mods/src/chat/chat.cpp @@ -21,12 +21,12 @@ // Send API Command std::string chat_send_api_command(Minecraft *minecraft, std::string str) { - struct ConnectedClient client; + ConnectedClient client; client.sock = -1; client.str = ""; client.time = 0; CommandServer *command_server = minecraft->command_server; - if (command_server != NULL) { + if (command_server != nullptr) { return CommandServer_parse(command_server, &client, &str); } else { return ""; @@ -36,7 +36,7 @@ std::string chat_send_api_command(Minecraft *minecraft, std::string str) { #ifndef MCPI_HEADLESS_MODE // Send API Chat Command static void send_api_chat_command(Minecraft *minecraft, char *str) { - char *command = NULL; + char *command = nullptr; safe_asprintf(&command, "chat.post(%s)\n", str); chat_send_api_command(minecraft, command); free(command); @@ -48,7 +48,7 @@ std::string _chat_get_prefix(char *username) { return std::string("<") + username + "> "; } void chat_send_message(ServerSideNetworkHandler *server_side_network_handler, char *username, char *message) { - char *full_message = NULL; + char *full_message = nullptr; safe_asprintf(&full_message, "%s%s", _chat_get_prefix(username).c_str(), message); sanitize_string(&full_message, MAX_CHAT_MESSAGE_LENGTH, 0); std::string cpp_string = full_message; @@ -72,7 +72,7 @@ void chat_handle_packet_send(Minecraft *minecraft, ChatPacket *packet) { // Manually Send (And Loopback) ChatPacket static void CommandServer_parse_CommandServer_dispatchPacket_injection(CommandServer *command_server, Packet *packet) { Minecraft *minecraft = command_server->minecraft; - if (minecraft != NULL) { + if (minecraft != nullptr) { chat_handle_packet_send(minecraft, (ChatPacket *) packet); } } @@ -80,7 +80,7 @@ static void CommandServer_parse_CommandServer_dispatchPacket_injection(CommandSe // Handle ChatPacket Server-Side static void ServerSideNetworkHandler_handle_ChatPacket_injection(ServerSideNetworkHandler *server_side_network_handler, RakNet_RakNetGUID *rak_net_guid, ChatPacket *chat_packet) { Player *player = ServerSideNetworkHandler_getPlayer(server_side_network_handler, rak_net_guid); - if (player != NULL) { + if (player != nullptr) { const char *username = player->username.c_str(); const char *message = chat_packet->message.c_str(); chat_send_message(server_side_network_handler, (char *) username, (char *) message); @@ -116,7 +116,7 @@ void init_chat() { // Manually Send (And Loopback) ChatPacket overwrite_call((void *) 0x6b518, (void *) CommandServer_parse_CommandServer_dispatchPacket_injection); // Re-Broadcast ChatPacket - patch_address(ServerSideNetworkHandler_handle_ChatPacket_vtable_addr, (void *) ServerSideNetworkHandler_handle_ChatPacket_injection); + patch_address(ServerSideNetworkHandler_handle_ChatPacket_vtable_addr, ServerSideNetworkHandler_handle_ChatPacket_injection); #ifndef MCPI_HEADLESS_MODE // Send Messages On Input Tick input_run_on_tick(send_queued_messages); diff --git a/mods/src/chat/ui.cpp b/mods/src/chat/ui.cpp index 692728f..1c151bc 100644 --- a/mods/src/chat/ui.cpp +++ b/mods/src/chat/ui.cpp @@ -69,8 +69,9 @@ CUSTOM_VTABLE(chat_screen, Screen) { original_render(super, x, y, param_1); }; // Positioning + static Screen_setupPositions_t original_setupPositions = vtable->setupPositions; vtable->setupPositions = [](Screen *super) { - Screen_setupPositions_non_virtual(super); + original_setupPositions(super); ChatScreen *self = (ChatScreen *) super; self->send->height = 24; self->send->width = 40; @@ -95,7 +96,7 @@ CUSTOM_VTABLE(chat_screen, Screen) { } _chat_queue_message(text.c_str()); } - Minecraft_setScreen(super->minecraft, NULL); + Minecraft_setScreen(super->minecraft, nullptr); } else if (key == 0x26) { // Up local_history.at(self->history_pos) = self->chat->getText(); @@ -118,6 +119,7 @@ CUSTOM_VTABLE(chat_screen, Screen) { original_keyPressed(super, key); }; // Button Click + static Screen_buttonClicked_t original_buttonClicked = vtable->buttonClicked; vtable->buttonClicked = [](Screen *super, Button *button) { ChatScreen *self = (ChatScreen *) super; if (button == self->send) { @@ -126,7 +128,7 @@ CUSTOM_VTABLE(chat_screen, Screen) { super->vtable->keyPressed(super, 0x0d); } else { // Call Original Method - Screen_buttonClicked_non_virtual(super, button); + original_buttonClicked(super, button); } }; } @@ -147,7 +149,7 @@ static Screen *create_chat_screen() { void _init_chat_ui() { misc_run_on_game_key_press([](Minecraft *minecraft, int key) { if (key == 0x54) { - if (Minecraft_isLevelGenerated(minecraft) && minecraft->screen == NULL) { + if (Minecraft_isLevelGenerated(minecraft) && minecraft->screen == nullptr) { Minecraft_setScreen(minecraft, create_chat_screen()); } return true; diff --git a/mods/src/compat/bcm_host.c b/mods/src/compat/bcm_host.cpp similarity index 100% rename from mods/src/compat/bcm_host.c rename to mods/src/compat/bcm_host.cpp diff --git a/mods/src/compat/compat.c b/mods/src/compat/compat.cpp similarity index 94% rename from mods/src/compat/compat.c rename to mods/src/compat/compat.cpp index cff6a39..980c738 100644 --- a/mods/src/compat/compat.c +++ b/mods/src/compat/compat.cpp @@ -1,6 +1,6 @@ #include -#include -#include +#include +#include #include #include @@ -51,7 +51,7 @@ HOOK(SDL_PollEvent, int, (SDL_Event *event)) { int ret = real_SDL_PollEvent(event); // Handle Events - if (ret == 1 && event != NULL) { + if (ret == 1 && event != nullptr) { int handled = 0; #ifndef MCPI_HEADLESS_MODE @@ -116,11 +116,10 @@ static void exit_handler(__attribute__((unused)) int data) { void init_compat() { // Install Signal Handlers signal(SIGINT, SIG_IGN); - struct sigaction act_sigterm; - memset((void *) &act_sigterm, 0, sizeof (struct sigaction)); + struct sigaction act_sigterm = {}; act_sigterm.sa_flags = SA_RESTART; act_sigterm.sa_handler = &exit_handler; - sigaction(SIGTERM, &act_sigterm, NULL); + sigaction(SIGTERM, &act_sigterm, nullptr); // Patches _patch_egl_calls(); _patch_x11_calls(); diff --git a/mods/src/compat/egl.c b/mods/src/compat/egl.cpp similarity index 97% rename from mods/src/compat/egl.c rename to mods/src/compat/egl.cpp index 5c9d01c..21f7a6b 100644 --- a/mods/src/compat/egl.c +++ b/mods/src/compat/egl.cpp @@ -6,13 +6,13 @@ // Functions That Have Their Return Values Used static EGLSurface eglCreateWindowSurface_injection(__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLConfig config, __attribute__((unused)) NativeWindowType native_window, __attribute__((unused)) EGLint const *attrib_list) { - return 0; + return nullptr; } static EGLDisplay eglGetDisplay_injection(__attribute__((unused)) NativeDisplayType native_display) { - return 0; + return nullptr; } static EGLContext eglCreateContext_injection(__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLConfig config, __attribute__((unused)) EGLContext share_context, __attribute__((unused)) EGLint const *attrib_list) { - return 0; + return nullptr; } // Call media_swap_buffers() static EGLBoolean eglSwapBuffers_injection(__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLSurface surface) { diff --git a/mods/src/compat/x11.c b/mods/src/compat/x11.cpp similarity index 96% rename from mods/src/compat/x11.c rename to mods/src/compat/x11.cpp index ab87d30..b0dadec 100644 --- a/mods/src/compat/x11.c +++ b/mods/src/compat/x11.cpp @@ -13,7 +13,7 @@ static int XTranslateCoordinates_injection(__attribute__((unused)) void *display } static int XGetWindowAttributes_injection(__attribute__((unused)) void *display, __attribute__((unused)) XID w, XWindowAttributes *window_attributes_return) { // Use MCPI Replacemnt Function - XWindowAttributes attributes; + XWindowAttributes attributes = {}; attributes.x = 0; attributes.y = 0; media_get_framebuffer_size(&attributes.width, &attributes.height); diff --git a/mods/src/death/death.cpp b/mods/src/death/death.cpp index 487faba..c4efb61 100644 --- a/mods/src/death/death.cpp +++ b/mods/src/death/death.cpp @@ -65,19 +65,19 @@ std::string get_death_message(Player *player, Entity *cause, bool was_shot = fal } static bool is_hurt = false; -static bool Mob_hurt_injection(Mob *mob, Entity *source, int dmg) { - // Call Original Method +static bool Mob_hurt_injection(Mob_hurt_t original, Mob *mob, Entity *source, int dmg) { is_hurt = true; - bool ret = Mob_hurt_non_virtual(mob, source, dmg); + bool ret = original(mob, source, dmg); is_hurt = false; return ret; } // Death Message Logic -#define Player_death_injections(type) \ - static void type##Player_die_injection(type##Player *player, Entity *cause) { \ +#define Player_die_injections(type) \ + static type##_die_t original_##type##_die; \ + static void type##_die_injection(type *player, Entity *cause) { \ /* Call Original Method */ \ - type##Player_die_non_virtual(player, cause); \ + original_##type##_die(player, cause); \ \ /* Get Variable */ \ RakNetInstance *rak_net_instance = player->minecraft->rak_net_instance; \ @@ -90,14 +90,14 @@ static bool Mob_hurt_injection(Mob *mob, Entity *source, int dmg) { ServerSideNetworkHandler *server_side_network_handler = (ServerSideNetworkHandler *) player->minecraft->network_handler; \ ServerSideNetworkHandler_displayGameMessage(server_side_network_handler, &message); \ } \ - } \ - \ - static void type##Player_actuallyHurt_injection(type##Player *player, int32_t damage) { \ + } +#define Player_actuallyHurt_injections(type) \ + static void type##_actuallyHurt_injection(type *player, int32_t damage) { \ /* Store Old Health */ \ int32_t old_health = player->health; \ \ /* Call Original Method */ \ - type##Player_actuallyHurt_non_virtual(player, damage); \ + (*Mob_actuallyHurt_vtable_addr)((Mob *) player, damage); \ if (is_hurt == true) return; \ \ /* Store New Health */ \ @@ -110,7 +110,7 @@ static bool Mob_hurt_injection(Mob *mob, Entity *source, int dmg) { /* Check Health */ \ if (new_health < 1 && old_health >= 1) { \ /* Get Death Message */ \ - std::string message = get_death_message((Player *) player, NULL); \ + std::string message = get_death_message((Player *) player, nullptr); \ \ /* Post Death Message */ \ ServerSideNetworkHandler *server_side_network_handler = (ServerSideNetworkHandler *) player->minecraft->network_handler; \ @@ -119,22 +119,25 @@ static bool Mob_hurt_injection(Mob *mob, Entity *source, int dmg) { } \ } -Player_death_injections(Local); -Player_death_injections(Server); +Player_die_injections(LocalPlayer) +Player_die_injections(ServerPlayer) + +Player_actuallyHurt_injections(LocalPlayer) +Player_actuallyHurt_injections(ServerPlayer) // Init void init_death() { // Death Messages if (feature_has("Implement Death Messages", server_auto)) { - patch_address(ServerPlayer_die_vtable_addr, (void *) ServerPlayer_die_injection); - patch_address(LocalPlayer_die_vtable_addr, (void *) LocalPlayer_die_injection); - patch_address(ServerPlayer_actuallyHurt_vtable_addr, (void *) ServerPlayer_actuallyHurt_injection); - patch_address(LocalPlayer_actuallyHurt_vtable_addr, (void *) LocalPlayer_actuallyHurt_injection); - overwrite_calls((void *) Mob_hurt_non_virtual, (void *) Mob_hurt_injection); + patch_address(ServerPlayer_die_vtable_addr, ServerPlayer_die_injection); + patch_address(LocalPlayer_die_vtable_addr, LocalPlayer_die_injection); + patch_address(LocalPlayer_actuallyHurt_vtable_addr, LocalPlayer_actuallyHurt_injection); + patch_address(ServerPlayer_actuallyHurt_vtable_addr, ServerPlayer_actuallyHurt_injection); + overwrite_virtual_calls(Mob_hurt, Mob_hurt_injection); } // Fix TNT - // This changes PrimedTnt_explode from Level::explode(NULL, x, y, z, 3.1f) to Level::explode(this, x, y, z, 3.1f) + // This changes PrimedTnt_explode from Level::explode(nullptr, x, y, z, 3.1f) to Level::explode(this, x, y, z, 3.1f) unsigned char cpy_r1_r0_patch[4] = {0x00, 0x10, 0xa0, 0xe1}; // "cpy r1, r0" patch((void *) 0x87998, cpy_r1_r0_patch); unsigned char ldr_r0_24_patch[4] = {0x24, 0x00, 0x90, 0xe5}; // "ldr r0, [r0, #0x24]" diff --git a/mods/src/feature/feature.c b/mods/src/feature/feature.cpp similarity index 68% rename from mods/src/feature/feature.c rename to mods/src/feature/feature.cpp index 451a470..498530d 100644 --- a/mods/src/feature/feature.c +++ b/mods/src/feature/feature.cpp @@ -6,18 +6,18 @@ #include // Check For Feature -int _feature_has(const char *name) { +bool _feature_has(const char *name) { // Get Value char *env = getenv("MCPI_FEATURE_FLAGS"); - char *features = strdup(env != NULL ? env : ""); + char *features = strdup(env != nullptr ? env : ""); char *tok = strtok(features, "|"); - int ret = 0; - while (tok != NULL) { + bool ret = false; + while (tok != nullptr) { if (strcmp(tok, name) == 0) { - ret = 1; + ret = true; break; } - tok = strtok(NULL, "|"); + tok = strtok(nullptr, "|"); } free(features); diff --git a/mods/src/fps/fps.cpp b/mods/src/fps/fps.cpp index 3e2ec78..6bdc683 100644 --- a/mods/src/fps/fps.cpp +++ b/mods/src/fps/fps.cpp @@ -9,7 +9,7 @@ // Track FPS #define NANOSECONDS_IN_SECOND 1000000000ll static long long int get_time() { - struct timespec ts; + timespec ts = {}; clock_gettime(CLOCK_MONOTONIC_RAW, &ts); long long int a = (long long int) ts.tv_nsec; long long int b = ((long long int) ts.tv_sec) * NANOSECONDS_IN_SECOND; diff --git a/mods/src/game-mode/game-mode.c b/mods/src/game-mode/game-mode.cpp similarity index 68% rename from mods/src/game-mode/game-mode.c rename to mods/src/game-mode/game-mode.cpp index 44f8be7..3fd2087 100644 --- a/mods/src/game-mode/game-mode.c +++ b/mods/src/game-mode/game-mode.cpp @@ -8,16 +8,16 @@ static int is_survival = -1; // Patch Game Mode -static void set_is_survival(int new_is_survival) { +static void set_is_survival(bool new_is_survival) { if (is_survival != new_is_survival) { DEBUG("Setting Game Mode: %s", new_is_survival ? "Survival" : "Creative"); // Correct Inventpry UI - unsigned char inventory_patch[4] = {new_is_survival ? 0x00 : 0x01, 0x30, 0xa0, 0xe3}; // "mov r3, #0x0" or "mov r3, #0x1" + unsigned char inventory_patch[4] = {(unsigned char) (new_is_survival ? 0x00 : 0x01), 0x30, 0xa0, 0xe3}; // "mov r3, #0x0" or "mov r3, #0x1" patch((void *) 0x16efc, inventory_patch); // Use Correct Size For GameMode Object - unsigned char size_patch[4] = {new_is_survival ? SURVIVAL_MODE_SIZE : CREATOR_MODE_SIZE, 0x00, 0xa0, 0xe3}; // "mov r0, #SURVIVAL_MODE_SIZE" or "mov r0, #CREATOR_MODE_SIZE" + unsigned char size_patch[4] = {(unsigned char) (new_is_survival ? SURVIVAL_MODE_SIZE : CREATOR_MODE_SIZE), 0x00, 0xa0, 0xe3}; // "mov r0, #SURVIVAL_MODE_SIZE" or "mov r0, #CREATOR_MODE_SIZE" patch((void *) 0x16ee4, size_patch); // Replace Default CreatorMode Constructor With CreatorMode Or SurvivalMode Constructor @@ -28,21 +28,21 @@ static void set_is_survival(int new_is_survival) { } // Handle Gamemode Switching -static void Minecraft_setIsCreativeMode_injection(Minecraft *this, int32_t new_game_mode) { +static void Minecraft_setIsCreativeMode_injection(Minecraft_setIsCreativeMode_t original, Minecraft *self, int32_t new_game_mode) { set_is_survival(!new_game_mode); // Call Original Method - Minecraft_setIsCreativeMode(this, new_game_mode); + original(self, new_game_mode); } // Disable CreatorMode-Specific API Features (Polling Block Hits) In SurvivalMode, This Is Preferable To Crashing -static unsigned char *Minecraft_getCreator_injection(Minecraft *minecraft) { +static unsigned char *Minecraft_getCreator_injection(Minecraft_getCreator_t original, Minecraft *minecraft) { if (is_survival) { - // SurvivalMode, Return NULL - return NULL; + // SurvivalMode, Return nullptr + return nullptr; } else { // CreatorMode, Call Original Method - return Minecraft_getCreator(minecraft); + return original(minecraft); } } @@ -50,8 +50,8 @@ static unsigned char *Minecraft_getCreator_injection(Minecraft *minecraft) { void init_game_mode() { // Dynamic Game Mode Switching if (feature_has("Implement Game-Mode Switching", server_enabled)) { - set_is_survival(1); - overwrite_calls((void *) Minecraft_setIsCreativeMode, (void *) Minecraft_setIsCreativeMode_injection); + set_is_survival(true); + overwrite_calls(Minecraft_setIsCreativeMode, Minecraft_setIsCreativeMode_injection); // Replace CreatorLevel With ServerLevel (This Fixes Beds And Mob Spawning) overwrite_call((void *) 0x16f84, (void *) ServerLevel_constructor); @@ -61,7 +61,7 @@ void init_game_mode() { patch_address((void *) 0x17004, (void *) level_size); // Disable CreatorMode-Specific API Features (Polling Block Hits) In SurvivalMode, This Is Preferable To Crashing - overwrite_calls((void *) Minecraft_getCreator, (void *) Minecraft_getCreator_injection); + overwrite_calls(Minecraft_getCreator, Minecraft_getCreator_injection); } // Create World Dialog diff --git a/mods/src/game-mode/ui.cpp b/mods/src/game-mode/ui.cpp index 9dd5932..ad5154d 100644 --- a/mods/src/game-mode/ui.cpp +++ b/mods/src/game-mode/ui.cpp @@ -92,8 +92,9 @@ CUSTOM_VTABLE(create_world_screen, Screen) { Screen_drawString(super, super->font, &description, self->game_mode->x, self->game_mode->y + self->game_mode->height + description_padding, 0xa0a0a0); }; // Positioning + static Screen_setupPositions_t original_setupPositions = vtable->setupPositions; vtable->setupPositions = [](Screen *super) { - Screen_setupPositions_non_virtual(super); + original_setupPositions(super); CreateWorldScreen *self = (CreateWorldScreen *) super; // Height/Width int width = 120; @@ -234,7 +235,7 @@ static void create_world(Minecraft *minecraft, std::string name, bool is_creativ // Redirect Create World Button #define create_SelectWorldScreen_tick_injection(prefix) \ - static void prefix##SelectWorldScreen_tick_injection(prefix##SelectWorldScreen *screen) { \ + static void prefix##SelectWorldScreen_tick_injection(prefix##SelectWorldScreen_tick_t original, prefix##SelectWorldScreen *screen) { \ if (screen->should_create_world) { \ /* Open Screen */ \ Minecraft_setScreen(screen->minecraft, create_create_world_screen()); \ @@ -242,7 +243,7 @@ static void create_world(Minecraft *minecraft, std::string name, bool is_creativ screen->should_create_world = false; \ } else { \ /* Call Original Method */ \ - prefix##SelectWorldScreen_tick_non_virtual(screen); \ + original(screen); \ } \ } create_SelectWorldScreen_tick_injection() @@ -251,8 +252,8 @@ create_SelectWorldScreen_tick_injection(Touch_) // Init void _init_game_mode_ui() { // Hijack Create World Button - patch_address(SelectWorldScreen_tick_vtable_addr, (void *) SelectWorldScreen_tick_injection); - patch_address(Touch_SelectWorldScreen_tick_vtable_addr, (void *) Touch_SelectWorldScreen_tick_injection); + overwrite_virtual_calls(SelectWorldScreen_tick, SelectWorldScreen_tick_injection); + overwrite_virtual_calls(Touch_SelectWorldScreen_tick, Touch_SelectWorldScreen_tick_injection); } #else diff --git a/mods/src/home/home.c b/mods/src/home/home.cpp similarity index 91% rename from mods/src/home/home.c rename to mods/src/home/home.cpp index 2fe8bb6..a8f0c86 100644 --- a/mods/src/home/home.c +++ b/mods/src/home/home.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include @@ -8,9 +8,9 @@ // Get MCPI Home Directory char *home_get() { - static char *dir = NULL; + static char *dir = nullptr; // Load - if (dir == NULL) { + if (dir == nullptr) { safe_asprintf(&dir, "%s" HOME_SUBDIRECTORY_FOR_GAME_DATA, getenv("HOME")); } // Return diff --git a/mods/src/init/init.c b/mods/src/init/init.cpp similarity index 100% rename from mods/src/init/init.c rename to mods/src/init/init.cpp diff --git a/mods/src/input/attack.c b/mods/src/input/attack.cpp similarity index 84% rename from mods/src/input/attack.c rename to mods/src/input/attack.cpp index a981bc3..c421e9e 100644 --- a/mods/src/input/attack.c +++ b/mods/src/input/attack.cpp @@ -14,9 +14,9 @@ void input_set_is_left_click(int val) { } // Add Attacking To MouseBuildInput -static int32_t MouseBuildInput_tickBuild_injection(MouseBuildInput *mouse_build_input, Player *local_player, uint32_t *build_action_intention_return) { +static int32_t MouseBuildInput_tickBuild_injection(MouseBuildInput_tickBuild_t original, MouseBuildInput *mouse_build_input, Player *local_player, uint32_t *build_action_intention_return) { // Call Original Method - int32_t ret = MouseBuildInput_tickBuild_non_virtual(mouse_build_input, local_player, build_action_intention_return); + int32_t ret = original(mouse_build_input, local_player, build_action_intention_return); // Use Attack/Place BuildActionIntention If No Other Valid BuildActionIntention Was Selected And This Was Not A Repeated Left Click if (ret != 0 && is_left_click == 1 && *build_action_intention_return == 0xa) { @@ -36,7 +36,7 @@ static int32_t MouseBuildInput_tickBuild_injection(MouseBuildInput *mouse_build_ } // Fix Holding Attack -static bool last_player_attack_successful = 0; +static bool last_player_attack_successful = false; static bool Player_attack_Entity_hurt_injection(Entity *entity, Entity *attacker, int32_t damage) { // Call Original Method last_player_attack_successful = entity->vtable->hurt(entity, attacker, damage); @@ -45,7 +45,7 @@ static bool Player_attack_Entity_hurt_injection(Entity *entity, Entity *attacker static ItemInstance *Player_attack_Inventory_getSelected_injection(Inventory *inventory) { // Check If Attack Was Successful if (!last_player_attack_successful) { - return NULL; + return nullptr; } // Call Original Method @@ -56,7 +56,7 @@ static ItemInstance *Player_attack_Inventory_getSelected_injection(Inventory *in void _init_attack() { // Allow Attacking Mobs if (feature_has("Fix Attacking", server_disabled)) { - patch_address(MouseBuildInput_tickBuild_vtable_addr, (void *) MouseBuildInput_tickBuild_injection); + overwrite_virtual_calls(MouseBuildInput_tickBuild, MouseBuildInput_tickBuild_injection); // Fix Holding Attack overwrite_call((void *) 0x8fc1c, (void *) Player_attack_Entity_hurt_injection); diff --git a/mods/src/input/bow.c b/mods/src/input/bow.cpp similarity index 89% rename from mods/src/input/bow.c rename to mods/src/input/bow.cpp index 1a5ef50..c24411e 100644 --- a/mods/src/input/bow.c +++ b/mods/src/input/bow.cpp @@ -19,7 +19,7 @@ static void _handle_bow(Minecraft *minecraft) { if (fix_bow && !is_right_click) { GameMode *game_mode = minecraft->game_mode; LocalPlayer *player = minecraft->player; - if (player != NULL && game_mode != NULL && LocalPlayer_isUsingItem(player)) { + if (player != nullptr && game_mode != nullptr && LocalPlayer_isUsingItem(player)) { game_mode->vtable->releaseUsingItem(game_mode, (Player *) player); } } diff --git a/mods/src/input/drop.cpp b/mods/src/input/drop.cpp index d966f79..fce6287 100644 --- a/mods/src/input/drop.cpp +++ b/mods/src/input/drop.cpp @@ -25,10 +25,10 @@ void input_drop(int drop_slot) { // Handle Drop Item Presses static void _handle_drop(Minecraft *minecraft) { - if ((minecraft->screen == NULL) && (!creative_is_restricted() || !Minecraft_isCreativeMode(minecraft)) && (drop_item_presses > 0 || drop_slot_pressed)) { + if ((minecraft->screen == nullptr) && (!creative_is_restricted() || !Minecraft_isCreativeMode(minecraft)) && (drop_item_presses > 0 || drop_slot_pressed)) { // Get Player LocalPlayer *player = minecraft->player; - if (player != NULL) { + if (player != nullptr) { // Get Selected Slot int32_t selected_slot = misc_get_real_selected_slot((Player *) player); Inventory *inventory = player->inventory; @@ -36,7 +36,7 @@ static void _handle_drop(Minecraft *minecraft) { // Get Item ItemInstance *inventory_item = inventory->vtable->getItem(inventory, selected_slot); // Check - if (inventory_item != NULL && inventory_item->count > 0) { + if (inventory_item != nullptr && inventory_item->count > 0) { // Copy ItemInstance *dropped_item = new ItemInstance; ALLOC_CHECK(dropped_item); diff --git a/mods/src/input/input.cpp b/mods/src/input/input.cpp index 49c2c64..09a18d2 100644 --- a/mods/src/input/input.cpp +++ b/mods/src/input/input.cpp @@ -19,9 +19,9 @@ void input_run_on_tick(input_tick_function_t function) { } // Handle Input Fixes -static void Minecraft_tickInput_injection(Minecraft *minecraft) { +static void Minecraft_tickInput_injection(Minecraft_tickInput_t original, Minecraft *minecraft) { // Call Original Method - Minecraft_tickInput(minecraft); + original(minecraft); // Run Input Tick Functions for (input_tick_function_t function : get_input_tick_functions()) { @@ -44,7 +44,7 @@ void init_input() { _init_bow(); // Loop - overwrite_calls((void *) Minecraft_tickInput, (void *) Minecraft_tickInput_injection); + overwrite_calls(Minecraft_tickInput, Minecraft_tickInput_injection); // Allow Attacking Mobs _init_attack(); diff --git a/mods/src/input/misc.c b/mods/src/input/misc.cpp similarity index 76% rename from mods/src/input/misc.c rename to mods/src/input/misc.cpp index ac0a57a..a97c712 100644 --- a/mods/src/input/misc.c +++ b/mods/src/input/misc.cpp @@ -22,8 +22,8 @@ int input_back() { // Handle Back Button Presses static void _handle_back(Minecraft *minecraft) { - // If Minecraft's Level property is initialized, but Minecraft's Player property is NULL, then Minecraft::handleBack may crash. - if (minecraft->level != NULL && minecraft->player == NULL) { + // If Minecraft's Level property is initialized, but Minecraft's Player property is nullptr, then Minecraft::handleBack may crash. + if (minecraft->level != nullptr && minecraft->player == nullptr) { // Unable to safely run Minecraft::handleBack, deferring until safe. return; } @@ -38,24 +38,24 @@ static void _handle_back(Minecraft *minecraft) { static bool OptionsScreen_handleBackEvent_injection(OptionsScreen *screen, bool do_nothing) { if (!do_nothing) { Minecraft *minecraft = screen->minecraft; - Minecraft_setScreen(minecraft, NULL); + Minecraft_setScreen(minecraft, nullptr); } - return 1; + return true; } // Fix "Sleeping Beauty" Bug -static int32_t InBedScreen_handleBackEvent_injection(InBedScreen *screen, bool do_nothing) { +static bool InBedScreen_handleBackEvent_injection(InBedScreen *screen, bool do_nothing) { if (!do_nothing) { // Close Screen Minecraft *minecraft = screen->minecraft; - Minecraft_setScreen(minecraft, NULL); + Minecraft_setScreen(minecraft, nullptr); // Stop Sleeping LocalPlayer *player = minecraft->player; - if (player != NULL) { + if (player != nullptr) { player->vtable->stopSleepInBed(player, 1, 1, 1); } } - return 1; + return true; } // Set Mouse Grab State @@ -80,7 +80,7 @@ static void _handle_mouse_grab(Minecraft *minecraft) { // Block UI Interaction When Mouse Is Locked static bool Gui_tickItemDrop_Minecraft_isCreativeMode_call_injection(Minecraft *minecraft) { - bool is_in_game = minecraft->screen == NULL || minecraft->screen->vtable == (Screen_vtable *) Touch_IngameBlockSelectionScreen_vtable_base; + bool is_in_game = minecraft->screen == nullptr || minecraft->screen->vtable == (Screen_vtable *) Touch_IngameBlockSelectionScreen_vtable_base; if (!enable_misc || (SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_OFF && is_in_game)) { // Call Original Method return creative_is_restricted() && Minecraft_isCreativeMode(minecraft); @@ -91,10 +91,10 @@ static bool Gui_tickItemDrop_Minecraft_isCreativeMode_call_injection(Minecraft * } // Block UI Interaction When Mouse Is Locked -static void Gui_handleClick_injection(Gui *gui, int32_t param_2, int32_t param_3, int32_t param_4) { +static void Gui_handleClick_injection(Gui_handleClick_t original, Gui *gui, int32_t param_2, int32_t param_3, int32_t param_4) { if (SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_OFF) { // Call Original Method - Gui_handleClick(gui, param_2, param_3, param_4); + original(gui, param_2, param_3, param_4); } } @@ -103,11 +103,11 @@ void _init_misc() { enable_misc = feature_has("Miscellaneous Input Fixes", server_disabled); if (enable_misc) { // Fix OptionsScreen Ignoring The Back Button - patch_address(OptionsScreen_handleBackEvent_vtable_addr, (void *) OptionsScreen_handleBackEvent_injection); + patch_address(OptionsScreen_handleBackEvent_vtable_addr, OptionsScreen_handleBackEvent_injection); // Fix "Sleeping Beauty" Bug - patch_address(InBedScreen_handleBackEvent_vtable_addr, (void *) InBedScreen_handleBackEvent_injection); + patch_address(InBedScreen_handleBackEvent_vtable_addr, InBedScreen_handleBackEvent_injection); // Disable Opening Inventory Using The Cursor When Cursor Is Hidden - overwrite_calls((void *) Gui_handleClick, (void *) Gui_handleClick_injection); + overwrite_calls(Gui_handleClick, Gui_handleClick_injection); } // Disable Item Dropping Using The Cursor When Cursor Is Hidden overwrite_call((void *) 0x27800, (void *) Gui_tickItemDrop_Minecraft_isCreativeMode_call_injection); diff --git a/mods/src/input/toggle.c b/mods/src/input/toggle.cpp similarity index 77% rename from mods/src/input/toggle.c rename to mods/src/input/toggle.cpp index cbfe1a7..5fff22d 100644 --- a/mods/src/input/toggle.c +++ b/mods/src/input/toggle.cpp @@ -12,13 +12,13 @@ static bool _handle_toggle_options(Minecraft *minecraft, int key) { if (key == 0x70) { // Toggle Hide GUI options->hide_gui = options->hide_gui ^ 1; - return 1; + return true; } else if (key == 0x74) { // Toggle Third Person options->third_person = (options->third_person + 1) % 3; - return 1; + return true; } else { - return 0; + return false; } } static void _fix_third_person(Minecraft *minecraft) { @@ -32,7 +32,7 @@ static void _fix_third_person(Minecraft *minecraft) { // Font-Facing View static void invert_rotation(Entity *entity) { - if (entity != NULL) { + if (entity != nullptr) { entity->yaw = 180.f + entity->yaw; entity->old_yaw = 180.f + entity->old_yaw; entity->pitch = -entity->pitch; @@ -40,7 +40,7 @@ static void invert_rotation(Entity *entity) { } } static void revert_rotation(Entity *entity) { - if (entity != NULL) { + if (entity != nullptr) { entity->yaw = -180.f + entity->yaw; entity->old_yaw = -180.f + entity->old_yaw; entity->pitch = -entity->pitch; @@ -48,8 +48,8 @@ static void revert_rotation(Entity *entity) { } } static int is_front_facing = 0; -static LocalPlayer *stored_player = NULL; -static void GameRenderer_setupCamera_injection(GameRenderer *game_renderer, float param_1, int param_2) { +static LocalPlayer *stored_player = nullptr; +static void GameRenderer_setupCamera_injection(GameRenderer_setupCamera_t original, GameRenderer *game_renderer, float param_1, int param_2) { // Get Objects Minecraft *minecraft = game_renderer->minecraft; stored_player = minecraft->player; @@ -64,21 +64,21 @@ static void GameRenderer_setupCamera_injection(GameRenderer *game_renderer, floa } // Call Original Method - GameRenderer_setupCamera(game_renderer, param_1, param_2); + original(game_renderer, param_1, param_2); // Revert if (is_front_facing) { revert_rotation((Entity *) stored_player); } } -static void ParticleEngine_render_injection(ParticleEngine *particle_engine, Entity *entity, float param_2) { +static void ParticleEngine_render_injection(ParticleEngine_render_t original, ParticleEngine *particle_engine, Entity *entity, float param_2) { // Invert Rotation if (is_front_facing && (Entity *) stored_player == entity) { invert_rotation((Entity *) stored_player); } // Call Original Method - ParticleEngine_render(particle_engine, entity, param_2); + original(particle_engine, entity, param_2); // Revert if (is_front_facing && (Entity *) stored_player == entity) { @@ -93,7 +93,7 @@ void _init_toggle() { misc_run_on_update(_fix_third_person); // Font-Facing View - overwrite_calls((void *) GameRenderer_setupCamera, (void *) GameRenderer_setupCamera_injection); - overwrite_calls((void *) ParticleEngine_render, (void *) ParticleEngine_render_injection); + overwrite_calls(GameRenderer_setupCamera, GameRenderer_setupCamera_injection); + overwrite_calls(ParticleEngine_render, ParticleEngine_render_injection); } } diff --git a/mods/src/misc/api.cpp b/mods/src/misc/api.cpp index d947cae..5ea182f 100644 --- a/mods/src/misc/api.cpp +++ b/mods/src/misc/api.cpp @@ -1,3 +1,4 @@ +#include #include #include @@ -26,9 +27,9 @@ // Run Functions On Update SETUP_CALLBACK(update, Minecraft); // Handle Custom Update Behavior -static void Minecraft_update_injection(Minecraft *minecraft) { +static void Minecraft_update_injection(Minecraft_update_t original, Minecraft *minecraft) { // Call Original Method - Minecraft_update_non_virtual(minecraft); + original(minecraft); // Run Functions handle_misc_update(minecraft); @@ -37,9 +38,9 @@ static void Minecraft_update_injection(Minecraft *minecraft) { // Run Functions On Tick SETUP_CALLBACK(tick, Minecraft); // Handle Custom Tick Behavior -static void Minecraft_tick_injection(Minecraft *minecraft, int32_t param_1, int32_t param_2) { +static void Minecraft_tick_injection(Minecraft_tick_t original, Minecraft *minecraft, int32_t param_1, int32_t param_2) { // Call Original Method - Minecraft_tick(minecraft, param_1, param_2); + original(minecraft, param_1, param_2); // Run Functions handle_misc_tick(minecraft); @@ -48,9 +49,9 @@ static void Minecraft_tick_injection(Minecraft *minecraft, int32_t param_1, int3 // Run Functions On Recipes Setup SETUP_CALLBACK(recipes_setup, Recipes); // Handle Custom Recipes Setup Behavior -static Recipes *Recipes_injection(Recipes *recipes) { +static Recipes *Recipes_injection(Recipes_constructor_t original, Recipes *recipes) { // Call Original Method - Recipes_constructor(recipes); + original(recipes); // Run Functions handle_misc_recipes_setup(recipes); @@ -62,9 +63,9 @@ static Recipes *Recipes_injection(Recipes *recipes) { // Run Functions On Furnace Recipes Setup SETUP_CALLBACK(furnace_recipes_setup, FurnaceRecipes); // Handle Custom Furnace Recipes Setup Behavior -static FurnaceRecipes *FurnaceRecipes_injection(FurnaceRecipes *recipes) { +static FurnaceRecipes *FurnaceRecipes_injection(FurnaceRecipes_constructor_t original, FurnaceRecipes *recipes) { // Call Original Method - FurnaceRecipes_constructor(recipes); + original(recipes); // Run Functions handle_misc_furnace_recipes_setup(recipes); @@ -87,34 +88,34 @@ static void Inventory_setupDefault_FillingContainer_addItem_call_injection(Filli // Run Functions On Tiles Setup SETUP_CALLBACK(tiles_setup, void); // Handle Custom Tiles Setup Behavior -static void Tile_initTiles_injection() { +static void Tile_initTiles_injection(Tile_initTiles_t original) { // Run Functions - handle_misc_tiles_setup(NULL); + handle_misc_tiles_setup(nullptr); // Call Original Method - Tile_initTiles(); + original(); } // Run Functions On Items Setup SETUP_CALLBACK(items_setup, void); // Handle Custom Items Setup Behavior -static void Item_initItems_injection() { +static void Item_initItems_injection(Item_initItems_t original) { // Call Original Method - Item_initItems(); + original(); // Run Functions - handle_misc_items_setup(NULL); + handle_misc_items_setup(nullptr); } // Run Functions On Language Setup SETUP_CALLBACK(language_setup, void); // Handle Custom Items Setup Behavior -static void I18n_loadLanguage_injection(AppPlatform *app, std::string language_name) { +static void I18n_loadLanguage_injection(I18n_loadLanguage_t original, AppPlatform *app, std::string language_name) { // Call Original Method - I18n_loadLanguage(app, language_name); + original(app, std::move(language_name)); // Run Functions - handle_misc_language_setup(NULL); + handle_misc_language_setup(nullptr); } // Run Functions On GUI Key Press @@ -128,32 +129,32 @@ static bool handle_misc_game_key_press(Minecraft *minecraft, int key) { return false; } // Handle Key Presses -static void Gui_handleKeyPressed_injection(Gui *self, int key) { +static void Gui_handleKeyPressed_injection(Gui_handleKeyPressed_t original, Gui *self, int key) { // Run Functions if (handle_misc_game_key_press(self->minecraft, key)) { return; } // Call Original Method - Gui_handleKeyPressed(self, key); + original(self, key); } // Init void _init_misc_api() { // Handle Custom Update Behavior - overwrite_calls((void *) Minecraft_update_non_virtual, (void *) Minecraft_update_injection); + overwrite_virtual_calls(Minecraft_update, Minecraft_update_injection); // Handle Custom Tick Behavior - overwrite_calls((void *) Minecraft_tick, (void *) Minecraft_tick_injection); + overwrite_calls(Minecraft_tick, Minecraft_tick_injection); // Handle Custom Recipe Setup Behavior - overwrite_calls((void *) Recipes_constructor, (void *) Recipes_injection); - overwrite_calls((void *) FurnaceRecipes_constructor, (void *) FurnaceRecipes_injection); + overwrite_calls(Recipes_constructor, Recipes_injection); + overwrite_calls(FurnaceRecipes_constructor, 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); + overwrite_calls(Tile_initTiles, Tile_initTiles_injection); + overwrite_calls(Item_initItems, Item_initItems_injection); // Handle Custom Language Entries - overwrite_calls((void *) I18n_loadLanguage, (void *) I18n_loadLanguage_injection); + overwrite_calls(I18n_loadLanguage, I18n_loadLanguage_injection); // Handle Key Presses - overwrite_calls((void *) Gui_handleKeyPressed, (void *) Gui_handleKeyPressed_injection); + overwrite_calls(Gui_handleKeyPressed, Gui_handleKeyPressed_injection); } diff --git a/mods/src/misc/logging.cpp b/mods/src/misc/logging.cpp index 7532173..a516b59 100644 --- a/mods/src/misc/logging.cpp +++ b/mods/src/misc/logging.cpp @@ -8,7 +8,7 @@ // Print Chat To Log static bool Gui_addMessage_recursing = false; -static void Gui_addMessage_injection(Gui *gui, std::string *text) { +static void Gui_addMessage_injection(Gui_addMessage_t original, Gui *gui, std::string *text) { // Sanitize Message char *new_message = strdup(text->c_str()); ALLOC_CHECK(new_message); @@ -26,26 +26,22 @@ static void Gui_addMessage_injection(Gui *gui, std::string *text) { free(safe_message); // Call Original Method - Gui_addMessage(gui, &cpp_str); + original(gui, &cpp_str); // End Recursing Gui_addMessage_recursing = false; } else { // Call Original Method - Gui_addMessage(gui, &cpp_str); + original(gui, &cpp_str); } // Free free(new_message); } -void misc_add_message(Gui *gui, const char *text) { - std::string str = text; - Gui_addMessage_injection(gui, &str); -} // Print Progress Reports static int last_progress = -1; -static const char *last_message = NULL; +static const char *last_message = nullptr; static void print_progress(Minecraft *minecraft) { const char *message = Minecraft_getProgressMessage(minecraft); int32_t progress = minecraft->progress; @@ -53,7 +49,7 @@ static void print_progress(Minecraft *minecraft) { message = "Ready"; progress = -1; } - if (message != NULL) { + if (message != nullptr) { bool message_different = message != last_message; bool progress_significant = is_progress_difference_significant(progress, last_progress); if (message_different || progress_significant) { @@ -79,25 +75,25 @@ static void Minecraft_update_injection(Minecraft *minecraft) { } // Log When Game Is Saved -void Level_saveLevelData_injection(Level *level) { +static void Level_saveLevelData_injection(Level_saveLevelData_t original, Level *level) { // Print Log Message DEBUG("Saving Game"); // Call Original Method - Level_saveLevelData(level); + original(level); } // Init void _init_misc_logging() { // Print Chat To Log - overwrite_calls((void *) Gui_addMessage, (void *) Gui_addMessage_injection); + overwrite_calls(Gui_addMessage, Gui_addMessage_injection); // Print Progress Reports misc_run_on_update(Minecraft_update_injection); // Print Log On Game Save - overwrite_calls((void *) Level_saveLevelData, (void *) Level_saveLevelData_injection); + overwrite_calls(Level_saveLevelData, Level_saveLevelData_injection); // Disable stdout Buffering - setvbuf(stdout, NULL, _IONBF, 0); + setvbuf(stdout, nullptr, _IONBF, 0); } diff --git a/mods/src/misc/misc-internal.h b/mods/src/misc/misc-internal.h index 3f9e885..806dc41 100644 --- a/mods/src/misc/misc-internal.h +++ b/mods/src/misc/misc-internal.h @@ -4,7 +4,6 @@ extern "C" { #endif -__attribute__((visibility("internal"))) void _init_misc_cpp(); __attribute__((visibility("internal"))) void _init_misc_logging(); __attribute__((visibility("internal"))) void _init_misc_api(); diff --git a/mods/src/misc/misc.c b/mods/src/misc/misc.c deleted file mode 100644 index 332bd81..0000000 --- a/mods/src/misc/misc.c +++ /dev/null @@ -1,850 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#ifndef MCPI_HEADLESS_MODE -#include -#endif - -#include -#include - -#include -#include - -#include -#include -#include "misc-internal.h" -#include - -// Heart food overlay -static int heal_amount = 0, heal_amount_drawing = 0; -void Gui_renderHearts_injection(Gui *gui) { - // Get heal_amount - heal_amount = heal_amount_drawing = 0; - - Inventory *inventory = gui->minecraft->player->inventory; - ItemInstance *held_ii = Inventory_getSelected(inventory); - if (held_ii) { - Item *held = Item_items[held_ii->id]; - if (held->vtable->isFood(held) && held_ii->id) { - int nutrition = ((FoodItem *) held)->nutrition; - int cur_health = gui->minecraft->player->health; - int heal_num = fmin(cur_health + nutrition, 20) - cur_health; - heal_amount = heal_amount_drawing = heal_num; - } - } - - // Call original - Gui_renderHearts(gui); -} - -#define PINK_HEART_FULL 70 -#define PINK_HEART_HALF 79 -Gui_blit_t Gui_blit_renderHearts_original = NULL; -void Gui_renderHearts_GuiComponent_blit_overlay_empty_injection(Gui *gui, int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t w1, int32_t h1, int32_t w2, int32_t h2) { - // Call original - Gui_blit_renderHearts_original(gui, x1, y1, x2, y2, w1, h1, w2, h2); - // Render the overlay - if (heal_amount_drawing == 1) { - // Half heart - Gui_blit_renderHearts_original(gui, x1, y1, PINK_HEART_HALF, 0, w1, h1, w2, h2); - heal_amount_drawing = 0; - } else if (heal_amount_drawing > 0) { - // Full heart - Gui_blit_renderHearts_original(gui, x1, y1, PINK_HEART_FULL, 0, w1, h1, w2, h2); - heal_amount_drawing -= 2; - } -} - -void Gui_renderHearts_GuiComponent_blit_overlay_hearts_injection(Gui *gui, int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t w1, int32_t h1, int32_t w2, int32_t h2) { - // Offset the overlay - if (x2 == 52) { - heal_amount_drawing += 2; - } else if (x2 == 61 && heal_amount) { - // Half heart, flipped - Gui_blit_renderHearts_original(gui, x1, y1, PINK_HEART_FULL, 0, w1, h1, w2, h2); - heal_amount_drawing += 1; - }; - // Call original - Gui_blit_renderHearts_original(gui, x1, y1, x2, y2, w1, h1, w2, h2); - heal_amount_drawing = fmin(heal_amount_drawing, heal_amount); -} - -// Classic HUD -#define DEFAULT_HUD_PADDING 2 -#define NEW_HUD_PADDING 1 -#define HUD_ELEMENT_WIDTH 82 -#define HUD_ELEMENT_HEIGHT 9 -#define TOOLBAR_HEIGHT 22 -#define SLOT_WIDTH 20 -#define DEFAULT_BUBBLES_PADDING 1 -#define NUMBER_OF_SLOTS 9 -static int use_classic_hud = 0; -static void Gui_renderHearts_GuiComponent_blit_hearts_injection(Gui *component, int32_t x_dest, int32_t y_dest, int32_t x_src, int32_t y_src, int32_t width_dest, int32_t height_dest, int32_t width_src, int32_t height_src) { - Minecraft *minecraft = component->minecraft; - x_dest -= DEFAULT_HUD_PADDING; - float width = ((float) minecraft->screen_width) * Gui_InvGuiScale; - float height = ((float) minecraft->screen_height) * Gui_InvGuiScale; - x_dest += (width - (NUMBER_OF_SLOTS * SLOT_WIDTH)) / 2; - y_dest -= DEFAULT_HUD_PADDING; - y_dest += height - HUD_ELEMENT_HEIGHT - TOOLBAR_HEIGHT - NEW_HUD_PADDING; - // Call Original Method - Gui_blit(component, x_dest, y_dest, x_src, y_src, width_dest, height_dest, width_src, height_src); -} -static void Gui_renderHearts_GuiComponent_blit_armor_injection(Gui *component, int32_t x_dest, int32_t y_dest, int32_t x_src, int32_t y_src, int32_t width_dest, int32_t height_dest, int32_t width_src, int32_t height_src) { - Minecraft *minecraft = component->minecraft; - x_dest -= DEFAULT_HUD_PADDING + HUD_ELEMENT_WIDTH; - float width = ((float) minecraft->screen_width) * Gui_InvGuiScale; - float height = ((float) minecraft->screen_height) * Gui_InvGuiScale; - x_dest += width - ((width - (NUMBER_OF_SLOTS * SLOT_WIDTH)) / 2) - HUD_ELEMENT_WIDTH; - y_dest -= DEFAULT_HUD_PADDING; - y_dest += height - HUD_ELEMENT_HEIGHT - TOOLBAR_HEIGHT - NEW_HUD_PADDING; - // Call Original Method - Gui_blit(component, x_dest, y_dest, x_src, y_src, width_dest, height_dest, width_src, height_src); -} -static void Gui_renderBubbles_GuiComponent_blit_injection(Gui *component, int32_t x_dest, int32_t y_dest, int32_t x_src, int32_t y_src, int32_t width_dest, int32_t height_dest, int32_t width_src, int32_t height_src) { - Minecraft *minecraft = component->minecraft; - x_dest -= DEFAULT_HUD_PADDING; - float width = ((float) minecraft->screen_width) * Gui_InvGuiScale; - float height = ((float) minecraft->screen_height) * Gui_InvGuiScale; - x_dest += (width - (NUMBER_OF_SLOTS * SLOT_WIDTH)) / 2; - y_dest -= DEFAULT_HUD_PADDING + DEFAULT_BUBBLES_PADDING + HUD_ELEMENT_HEIGHT; - y_dest += height - HUD_ELEMENT_HEIGHT - TOOLBAR_HEIGHT - HUD_ELEMENT_HEIGHT - NEW_HUD_PADDING; - // Call Original Method - Gui_blit(component, x_dest, y_dest, x_src, y_src, width_dest, height_dest, width_src, height_src); -} - -// Additional GUI Rendering -static int hide_chat_messages = 0; -bool is_in_chat = 0; -static int render_selected_item_text = 0; -static void Gui_renderChatMessages_injection(Gui *gui, int32_t y_offset, uint32_t max_messages, bool disable_fading, Font *font) { - // Handle Classic HUD - if (use_classic_hud) { - Minecraft *minecraft = gui->minecraft; - if (!Minecraft_isCreativeMode(minecraft)) { - y_offset -= (HUD_ELEMENT_HEIGHT * 2) + NEW_HUD_PADDING; - } - } - - // Call Original Method - if (!hide_chat_messages && !is_in_chat) { - Gui_renderChatMessages(gui, y_offset, max_messages, disable_fading, font); - } - - // Render Selected Item Text - if (render_selected_item_text) { - // Fix GL Mode -#ifndef MCPI_HEADLESS_MODE - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); -#endif - // Calculate Selected Item Text Scale - Minecraft *minecraft = gui->minecraft; - int32_t screen_width = minecraft->screen_width; - float scale = ((float) screen_width) * Gui_InvGuiScale; - // Render Selected Item Text - Gui_renderOnSelectItemNameText(gui, (int32_t) scale, font, y_offset - 0x13); - } -} -// Reset Selected Item Text Timer On Slot Select -static uint32_t reset_selected_item_text_timer = 0; -static void Gui_tick_injection(Gui *gui) { - // Call Original Method - Gui_tick(gui); - - // Handle Reset - if (render_selected_item_text) { - float *selected_item_text_timer = &gui->selected_item_text_timer; - if (reset_selected_item_text_timer) { - // Reset - *selected_item_text_timer = 0; - reset_selected_item_text_timer = 0; - } - } -} -// Trigger Reset Selected Item Text Timer On Slot Select -static void Inventory_selectSlot_injection(Inventory *inventory, int32_t slot) { - // Call Original Method - Inventory_selectSlot(inventory, slot); - - // Trigger Reset Selected Item Text Timer - if (render_selected_item_text) { - reset_selected_item_text_timer = 1; - } -} - -// Translucent Toolbar -static void Gui_renderToolBar_injection(Gui *gui, float param_1, int32_t param_2, int32_t param_3) { - // Call Original Method -#ifndef MCPI_HEADLESS_MODE - int was_blend_enabled = glIsEnabled(GL_BLEND); - if (!was_blend_enabled) { - glEnable(GL_BLEND); - } - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); -#endif - Gui_renderToolBar(gui, param_1, param_2, param_3); -#ifndef MCPI_HEADLESS_MODE - if (!was_blend_enabled) { - glDisable(GL_BLEND); - } -#endif -} -static void Gui_renderToolBar_glColor4f_injection(GLfloat red, GLfloat green, GLfloat blue, __attribute__((unused)) GLfloat alpha) { - // Fix Alpha -#ifndef MCPI_HEADLESS_MODE - glColor4f(red, green, blue, 1.0f); -#else - (void) red; - (void) green; - (void) blue; -#endif -} - -// Fix Screen Rendering When GUI is Hidden -static void Screen_render_injection(Screen *screen, int32_t param_1, int32_t param_2, float param_3) { - // Fix -#ifndef MCPI_HEADLESS_MODE - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); -#endif - // Call Original Method - Screen_render_non_virtual(screen, param_1, param_2, param_3); -} - -// Sanitize Username -#define MAX_USERNAME_LENGTH 16 -static void LoginPacket_read_injection(LoginPacket *packet, RakNet_BitStream *bit_stream) { - // Call Original Method - LoginPacket_read_non_virtual(packet, bit_stream); - - // Prepare - RakNet_RakString *rak_string = &packet->username; - // Get Original Username - RakNet_RakString_SharedString *shared_string = rak_string->sharedString; - char *c_str = shared_string->c_str; - // Sanitize - char *new_username = strdup(c_str); - ALLOC_CHECK(new_username); - sanitize_string(&new_username, MAX_USERNAME_LENGTH, 0); - // Set New Username - RakNet_RakString_Assign(rak_string, new_username); - // Free - free(new_username); -} - -// Fix RakNet::RakString Security Bug -// -// RakNet::RakString's format constructor is often given unsanitized user input and is never used for formatting, -// this is a massive security risk, allowing clients to run arbitrary format specifiers, this disables the -// formatting functionality. -static RakNet_RakString *RakNet_RakString_injection(RakNet_RakString *rak_string, const char *format, ...) { - // Call Original Method - return RakNet_RakString_constructor(rak_string, "%s", format); -} - -// Print Error Message If RakNet Startup Fails -static char *RAKNET_ERROR_NAMES[] = { - "Success", - "Already Started", - "Invalid Socket Descriptors", - "Invalid Max Connections", - "Socket Family Not Supported", - "Part Already In Use", - "Failed To Bind Port", - "Failed Test Send", - "Port Cannot Be 0", - "Failed To Create Network Thread", - "Couldn't Generate GUID", - "Unknown" -}; -#ifdef MCPI_SERVER_MODE -#define PRINT_RAKNET_STARTUP_FAILURE ERR -#else -#define PRINT_RAKNET_STARTUP_FAILURE WARN -#endif -static RakNet_StartupResult RakNetInstance_host_RakNet_RakPeer_Startup_injection(RakNet_RakPeer *rak_peer, unsigned short maxConnections, unsigned char *socketDescriptors, uint32_t socketDescriptorCount, int32_t threadPriority) { - // Call Original Method - RakNet_StartupResult result = rak_peer->vtable->Startup(rak_peer, maxConnections, socketDescriptors, socketDescriptorCount, threadPriority); - - // Print Error - if (result != RAKNET_STARTED) { - PRINT_RAKNET_STARTUP_FAILURE("Failed To Start RakNet: %s", RAKNET_ERROR_NAMES[result]); - } - - // Return - return result; -} - -// Fix Bug Where RakNetInstance Starts Pinging Potential Servers Before The "Join Game" Screen Is Opened -static RakNetInstance *RakNetInstance_injection(RakNetInstance *rak_net_instance) { - // Call Original Method - RakNetInstance *result = RakNetInstance_constructor(rak_net_instance); - // Fix - rak_net_instance->pinging_for_hosts = 0; - // Return - return result; -} - -// Close Current Screen On Death To Prevent Bugs -static void LocalPlayer_die_injection(LocalPlayer *entity, Entity *cause) { - // Close Screen - Minecraft *minecraft = entity->minecraft; - Minecraft_setScreen(minecraft, NULL); - - // Call Original Method - LocalPlayer_die_non_virtual(entity, cause); -} - -// Fix Furnace Not Checking Item Auxiliary When Inserting New Item -static int32_t FurnaceScreen_handleAddItem_injection(FurnaceScreen *furnace_screen, int32_t slot, ItemInstance *item) { - // Get Existing Item - FurnaceTileEntity *tile_entity = furnace_screen->tile_entity; - ItemInstance *existing_item = tile_entity->vtable->getItem(tile_entity, slot); - - // Check Item - int valid; - if (item->id == existing_item->id && item->auxiliary == existing_item->auxiliary) { - // Item Matches, Is Valid - valid = 1; - } else { - // Item Doesn't Match, Check If Existing Item Is Empty - if ((existing_item->id | existing_item->count | existing_item->auxiliary) == 0) { - // Existing Item Is Empty, Is Valid - valid = 1; - } else { - // Existing Item Isn't Empty, Isn't Valid - valid = 0; - } - } - - // Call Original Method - if (valid) { - // Valid - return FurnaceScreen_handleAddItem(furnace_screen, slot, item); - } else { - // Invalid - return 0; - } -} - -// Custom Cursor Rendering -// -// The default behavior for Touch GUI is to only render the cursor when the mouse is clicking, this fixes that. -// This also makes the cursor always render if the mouse is unlocked, instead of just when there is a Screen showing. -#ifndef MCPI_HEADLESS_MODE -static void GameRenderer_render_injection(GameRenderer *game_renderer, float param_1) { - // Call Original Method - GameRenderer_render(game_renderer, param_1); - - // Check If Cursor Should Render - if (SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_OFF) { - // Fix GL Mode - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - // Get X And Y - float x = Mouse_getX() * Gui_InvGuiScale; - float y = Mouse_getY() * Gui_InvGuiScale; - // Render Cursor - Minecraft *minecraft = game_renderer->minecraft; - Common_renderCursor(x, y, minecraft); - } -} -#endif - -// Get Real Selected Slot -int32_t misc_get_real_selected_slot(Player *player) { - // Get Selected Slot - Inventory *inventory = player->inventory; - int32_t selected_slot = inventory->selectedSlot; - - // Linked Slots - int32_t linked_slots_length = inventory->linked_slots_length; - if (selected_slot < linked_slots_length) { - int32_t *linked_slots = inventory->linked_slots; - selected_slot = linked_slots[selected_slot]; - } - - // Return - return selected_slot; -} - -#ifndef MCPI_HEADLESS_MODE -// Properly Generate Buffers -static void anGenBuffers_injection(int32_t count, uint32_t *buffers) { - glGenBuffers(count, buffers); -} -#endif - -// Fix Graphics Bug When Switching To First-Person While Sneaking -static void HumanoidMobRenderer_render_injection(HumanoidMobRenderer *model_renderer, Entity *entity, float param_2, float param_3, float param_4, float param_5, float param_6) { - HumanoidMobRenderer_render_non_virtual(model_renderer, entity, param_2, param_3, param_4, param_5, param_6); - HumanoidModel *model = model_renderer->model; - model->is_sneaking = 0; -} - -// Custom API Port -HOOK(bind, int, (int sockfd, const struct sockaddr *addr, socklen_t addrlen)) { - const struct sockaddr *new_addr = addr; - struct sockaddr_in in_addr; - if (addr->sa_family == AF_INET) { - in_addr = *(const struct sockaddr_in *) new_addr; - if (in_addr.sin_port == ntohs(4711)) { - const char *new_port_str = getenv("MCPI_API_PORT"); - long int new_port; - if (new_port_str != NULL && (new_port = strtol(new_port_str, NULL, 0)) != 0L) { - in_addr.sin_port = htons(new_port); - } - } - new_addr = (const struct sockaddr *) &in_addr; - } - ensure_bind(); - return real_bind(sockfd, new_addr, addrlen); -} - -// Change Grass Color -static int32_t get_color(LevelSource *level_source, int32_t x, int32_t z) { - Biome *biome = level_source->vtable->getBiome(level_source, x, z); - if (biome == NULL) { - return 0; - } - return biome->color; -} -#define BIOME_BLEND_SIZE 7 -static int32_t GrassTile_getColor_injection(__attribute__((unused)) Tile *tile, LevelSource *level_source, int32_t x, __attribute__((unused)) int32_t y, int32_t z) { - int r_sum = 0; - int g_sum = 0; - int b_sum = 0; - int color_sum = 0; - int x_start = x - (BIOME_BLEND_SIZE / 2); - int z_start = z - (BIOME_BLEND_SIZE / 2); - for (int x_offset = 0; x_offset < BIOME_BLEND_SIZE; x_offset++) { - for (int z_offset = 0; z_offset < BIOME_BLEND_SIZE; z_offset++) { - int32_t color = get_color(level_source, x_start + x_offset, z_start + z_offset); - r_sum += (color >> 16) & 0xff; - g_sum += (color >> 8) & 0xff; - b_sum += color & 0xff; - color_sum++; - } - } - int r_avg = r_sum / color_sum; - int g_avg = g_sum / color_sum; - int b_avg = b_sum / color_sum; - return (r_avg << 16) | (g_avg << 8) | b_avg; -} -static int32_t TallGrass_getColor_injection(TallGrass *tile, LevelSource *level_source, int32_t x, int32_t y, int32_t z) { - int32_t original_color = TallGrass_getColor_non_virtual(tile, level_source, x, y, z); - if (original_color == 0x339933) { - return GrassTile_getColor_injection((Tile *) tile, level_source, x, y, z); - } else { - return original_color; - } -} - -// Generate Caves -static void RandomLevelSource_buildSurface_injection(RandomLevelSource *random_level_source, int32_t chunk_x, int32_t chunk_y, unsigned char *chunk_data, Biome **biomes) { - // Call Original Method - RandomLevelSource_buildSurface(random_level_source, chunk_x, chunk_y, chunk_data, biomes); - - // Get Level - Level *level = random_level_source->level; - - // Get Cave Feature - LargeCaveFeature *cave_feature = &random_level_source->cave_feature; - - // Generate - cave_feature->vtable->apply(cave_feature, (ChunkSource *) random_level_source, level, chunk_x, chunk_y, chunk_data, 0); -} - -// No Block Tinting -static int32_t Tile_getColor_injection() { - return 0xffffff; -} - -// Disable Hostile AI In Creative Mode -static Entity *PathfinderMob_findAttackTarget_injection(PathfinderMob *mob) { - // Call Original Method - Entity *target = mob->vtable->findAttackTarget(mob); - - // Only modify the AI of monsters - if (mob->vtable->getCreatureBaseType(mob) != 1) { - return target; - } - - // Check If Creative Mode - if (target != NULL && target->vtable->isPlayer(target)) { - Player *player = (Player *) target; - Inventory *inventory = player->inventory; - bool is_creative = inventory->is_creative; - if (is_creative) { - target = NULL; - } - } - - // Return - return target; -} - -// 3D Chests -static int32_t Tile_getRenderShape_injection(Tile *tile) { - if (tile == Tile_chest) { - // Don't Render "Simple" Chest Model - return -1; - } else { - // Call Original Method - return tile->vtable->getRenderShape(tile); - } -} -static ChestTileEntity *ChestTileEntity_injection(ChestTileEntity *tile_entity) { - // Call Original Method - ChestTileEntity_constructor(tile_entity); - - // Enable Renderer - tile_entity->renderer_id = 1; - - // Return - return tile_entity; -} -static bool is_rendering_chest = 0; -static void ModelPart_render_injection(ModelPart *model_part, float scale) { - // Start - is_rendering_chest = 1; - - // Call Original Method - ModelPart_render(model_part, scale); - - // Stop - is_rendering_chest = 0; -} -static void Tesselator_vertexUV_injection(Tesselator *tesselator, float x, float y, float z, float u, float v) { - // Fix Chest Texture - if (is_rendering_chest) { - v /= 2; - } - - // Call Original Method - Tesselator_vertexUV(tesselator, x, y, z, u, v); -} -static bool ChestTileEntity_shouldSave_injection(__attribute__((unused)) unsigned char *tile_entity) { - return 1; -} - -// Animated 3D Chest -static ContainerMenu *ContainerMenu_injection(ContainerMenu *container_menu, Container *container, int32_t param_1) { - // Call Original Method - ContainerMenu_constructor(container_menu, container, param_1); - - // Play Animation - ChestTileEntity *tile_entity = (ChestTileEntity *) (((unsigned char *) container) - offsetof(ChestTileEntity, container)); - bool is_client = tile_entity->is_client; - if (!is_client) { - container->vtable->startOpen(container); - } - - // Return - return container_menu; -} -static ContainerMenu *ContainerMenu_destructor_injection(ContainerMenu *container_menu) { - // Play Animation - Container *container = container_menu->container; - ChestTileEntity *tile_entity = (ChestTileEntity *) (((unsigned char *) container) - offsetof(ChestTileEntity, container)); - bool is_client = tile_entity->is_client; - if (!is_client) { - container->vtable->stopOpen(container); - } - - // Call Original Method - return ContainerMenu_destructor_complete_non_virtual(container_menu); -} - -#ifndef MCPI_HEADLESS_MODE -// Custom Outline Color -static void glColor4f_injection(__attribute__((unused)) GLfloat red, __attribute__((unused)) GLfloat green, __attribute__((unused)) GLfloat blue, __attribute__((unused)) GLfloat alpha) { - // Set Color - glColor4f(0, 0, 0, 0.4); - - // Find Line Width - char *custom_line_width = getenv("MCPI_BLOCK_OUTLINE_WIDTH"); - float line_width; - if (custom_line_width != NULL) { - // Custom - line_width = strtof(custom_line_width, NULL); - } else { - // Guess - line_width = 2 / Gui_InvGuiScale; - } - // Clamp Line Width - float range[2]; - glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, range); - if (range[1] < line_width) { - line_width = range[1]; - } else if (range[0] > line_width) { - line_width = range[0]; - } - // Set Line Width - glLineWidth(line_width); -} -#endif - -// Fix Furnace Visual Bug -static int FurnaceTileEntity_getLitProgress_injection(FurnaceTileEntity *furnace, int max) { - // Call Original Method - int ret = FurnaceTileEntity_getLitProgress(furnace, max); - - // Fix Bug - if (ret > max) { - ret = max; - } - - // Return - return ret; -} - -// Fix used items transferring durability -static int selected_slot = -1; -static void Player_startUsingItem_injection(Player *self, ItemInstance *item_instance, int time) { - selected_slot = self->inventory->selectedSlot; - Player_startUsingItem(self, item_instance, time); -} -static void Player_stopUsingItem_injection(Player *self) { - if (selected_slot != self->inventory->selectedSlot) { - self->itemBeingUsed.id = 0; - } - Player_stopUsingItem(self); -} - -// Java Light Ramp -static void Dimension_updateLightRamp_injection(Dimension *self) { - // https://github.com/ReMinecraftPE/mcpe/blob/d7a8b6baecf8b3b050538abdbc976f690312aa2d/source/world/level/Dimension.cpp#L92-L105 - for (int i = 0; i <= 15; i++) { - float f1 = 1.0f - (((float) i) / 15.0f); - self->light_ramp[i] = ((1.0f - f1) / (f1 * 3.0f + 1.0f)) * (1.0f - 0.1f) + 0.1f; - // Default Light Ramp: - // float fVar4 = 1.0 - ((float) i * 0.0625); - // self->light_ramp[i] = ((1.0 - fVar4) / (fVar4 * 3.0 + 1.0)) * 0.95 + 0.15; - } -} - -// Init -static void nop() { -} -void init_misc() { - // Remove Invalid Item Background (A Red Background That Appears For Items That Are Not Included In The gui_blocks Atlas) - if (feature_has("Remove Invalid Item Background", server_disabled)) { - unsigned char invalid_item_background_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop" - patch((void *) 0x63c98, invalid_item_background_patch); - } - - - // Classic HUD - Gui_blit_renderHearts_original = Gui_blit; - if (feature_has("Classic HUD", server_disabled)) { - use_classic_hud = 1; - overwrite_call((void *) 0x26758, (void *) Gui_renderHearts_GuiComponent_blit_hearts_injection); - overwrite_call((void *) 0x2656c, (void *) Gui_renderHearts_GuiComponent_blit_armor_injection); - overwrite_call((void *) 0x268c4, (void *) Gui_renderBubbles_GuiComponent_blit_injection); - overwrite_call((void *) 0x266f8, (void *) Gui_renderHearts_GuiComponent_blit_hearts_injection); - overwrite_call((void *) 0x267c8, (void *) Gui_renderHearts_GuiComponent_blit_hearts_injection); - Gui_blit_renderHearts_original = Gui_renderHearts_GuiComponent_blit_hearts_injection; - } - - // Food overlay - if (feature_has("Food Overlay", server_disabled)) { - overwrite_calls((void *) Gui_renderHearts, Gui_renderHearts_injection); - overwrite_call((void *) 0x266f8, (void *) Gui_renderHearts_GuiComponent_blit_overlay_empty_injection); - overwrite_call((void *) 0x267c8, (void *) Gui_renderHearts_GuiComponent_blit_overlay_hearts_injection); - } - - // Render Selected Item Text + Hide Chat Messages - hide_chat_messages = feature_has("Hide Chat Messages", server_disabled); - render_selected_item_text = feature_has("Render Selected Item Text", server_disabled); - overwrite_calls((void *) Gui_renderChatMessages, (void *) Gui_renderChatMessages_injection); - overwrite_calls((void *) Gui_tick, (void *) Gui_tick_injection); - overwrite_calls((void *) Inventory_selectSlot, (void *) Inventory_selectSlot_injection); - - // Translucent Toolbar - if (feature_has("Translucent Toolbar", server_disabled)) { - overwrite_calls((void *) Gui_renderToolBar, (void *) Gui_renderToolBar_injection); - overwrite_call((void *) 0x26c5c, (void *) Gui_renderToolBar_glColor4f_injection); - } - - // Fix Screen Rendering When GUI is Hidden - overwrite_calls((void *) Screen_render_non_virtual, (void *) Screen_render_injection); - - // Sanitize Username - patch_address(LoginPacket_read_vtable_addr, (void *) LoginPacket_read_injection); - - // Fix RakNet::RakString Security Bug - overwrite_calls((void *) RakNet_RakString_constructor, (void *) RakNet_RakString_injection); - - // Print Error Message If RakNet Startup Fails - overwrite_call((void *) 0x73778, (void *) RakNetInstance_host_RakNet_RakPeer_Startup_injection); - - // Fix Bug Where RakNetInstance Starts Pinging Potential Servers Before The "Join Game" Screen Is Opened - overwrite_calls((void *) RakNetInstance_constructor, (void *) RakNetInstance_injection); - - // Close Current Screen On Death To Prevent Bugs - if (feature_has("Close Current Screen On Death", server_disabled)) { - patch_address(LocalPlayer_die_vtable_addr, (void *) LocalPlayer_die_injection); - } - - // Fix Furnace Not Checking Item Auxiliary When Inserting New Item - if (feature_has("Fix Furnace Not Checking Item Auxiliary", server_disabled)) { - overwrite_calls((void *) FurnaceScreen_handleAddItem, (void *) FurnaceScreen_handleAddItem_injection); - } - -#ifdef MCPI_HEADLESS_MODE - // Don't Render Game In Headless Mode - overwrite_calls((void *) GameRenderer_render, (void *) nop); - overwrite_calls((void *) NinecraftApp_initGLStates, (void *) nop); - overwrite_calls((void *) Gui_onConfigChanged, (void *) nop); - overwrite_calls((void *) LevelRenderer_generateSky, (void *) nop); -#else - // Improved Cursor Rendering - if (feature_has("Improved Cursor Rendering", server_disabled)) { - // Disable Normal Cursor Rendering - unsigned char disable_cursor_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop" - patch((void *) 0x4a6c0, disable_cursor_patch); - // Add Custom Cursor Rendering - overwrite_calls((void *) GameRenderer_render, (void *) GameRenderer_render_injection); - } -#endif - - // Disable V-Sync - if (feature_has("Disable V-Sync", server_enabled)) { - media_disable_vsync(); - } - - // Force EGL - if (feature_has("Force EGL", server_disabled)) { - media_force_egl(); - } - - // Remove Forced GUI Lag - if (feature_has("Remove Forced GUI Lag (Can Break Joining Servers)", server_enabled)) { - overwrite_calls((void *) Common_sleepMs, (void *) nop); - } - -#ifndef MCPI_HEADLESS_MODE - // Properly Generate Buffers - overwrite((void *) Common_anGenBuffers, (void *) anGenBuffers_injection); -#endif - - // Fix Graphics Bug When Switching To First-Person While Sneaking - patch_address(PlayerRenderer_render_vtable_addr, (void *) HumanoidMobRenderer_render_injection); - - // Disable Speed Bridging - if (feature_has("Disable Speed Bridging", server_disabled)) { - unsigned char disable_speed_bridging_patch[4] = {0x03, 0x00, 0x53, 0xe1}; // "cmp r3, r3" - patch((void *) 0x494b4, disable_speed_bridging_patch); - } - - // Disable Creative Mode Mining Delay - if (feature_has("Disable Creative Mode Mining Delay", server_disabled)) { - unsigned char nop_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop" - patch((void *) 0x19fa0, nop_patch); - } - - // Change Grass Color - if (feature_has("Add Biome Colors To Grass", server_disabled)) { - patch_address((void *) GrassTile_getColor_vtable_addr, (void *) GrassTile_getColor_injection); - patch_address((void *) TallGrass_getColor_vtable_addr, (void *) TallGrass_getColor_injection); - } - - // Generate Caves - if (feature_has("Generate Caves", server_auto)) { - overwrite_calls((void *) RandomLevelSource_buildSurface, (void *) RandomLevelSource_buildSurface_injection); - } - - // Disable Block Tinting - if (feature_has("Disable Block Tinting", server_disabled)) { - patch_address((void *) GrassTile_getColor_vtable_addr, (void *) Tile_getColor_injection); - patch_address((void *) TallGrass_getColor_vtable_addr, (void *) Tile_getColor_injection); - patch_address((void *) StemTile_getColor_vtable_addr, (void *) Tile_getColor_injection); - patch_address((void *) LeafTile_getColor_vtable_addr, (void *) Tile_getColor_injection); - overwrite((void *) LiquidTile_getColor_non_virtual, (void *) Tile_getColor_injection); - } - - // Custom GUI Scale - const char *gui_scale_str = getenv("MCPI_GUI_SCALE"); - if (gui_scale_str != NULL) { - unsigned char nop_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop" - patch((void *) 0x173e8, nop_patch); - patch((void *) 0x173f0, nop_patch); - float gui_scale = strtof(gui_scale_str, NULL); - uint32_t gui_scale_raw; - memcpy(&gui_scale_raw, &gui_scale, sizeof (gui_scale_raw)); - patch_address((void *) 0x17520, (void *) gui_scale_raw); - } - - // Disable Hostile AI In Creative Mode - if (feature_has("Disable Hostile AI In Creative Mode", server_enabled)) { - overwrite_call((void *) 0x83b8c, (void *) PathfinderMob_findAttackTarget_injection); - } - - // 3D Chests - if (feature_has("3D Chest Model", server_disabled)) { - overwrite_call((void *) 0x5e830, (void *) Tile_getRenderShape_injection); - overwrite_calls((void *) ChestTileEntity_constructor, (void *) ChestTileEntity_injection); - overwrite_call((void *) 0x6655c, (void *) ModelPart_render_injection); - overwrite_call((void *) 0x66568, (void *) ModelPart_render_injection); - overwrite_call((void *) 0x66574, (void *) ModelPart_render_injection); - overwrite_calls((void *) Tesselator_vertexUV, (void *) Tesselator_vertexUV_injection); - unsigned char chest_model_patch[4] = {0x13, 0x20, 0xa0, 0xe3}; // "mov r2, #0x13" - patch((void *) 0x66fc8, chest_model_patch); - unsigned char chest_color_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop" - patch((void *) 0x66404, chest_color_patch); - - // Animation - overwrite_calls((void *) ContainerMenu_constructor, (void *) ContainerMenu_injection); - overwrite_calls((void *) ContainerMenu_destructor_complete_non_virtual, (void *) ContainerMenu_destructor_injection); - } - patch_address((void *) 0x115b48, (void *) ChestTileEntity_shouldSave_injection); - -#ifndef MCPI_HEADLESS_MODE - // Replace Block Highlight With Outline - if (feature_has("Replace Block Highlight With Outline", server_disabled)) { - overwrite((void *) LevelRenderer_renderHitSelect, (void *) LevelRenderer_renderHitOutline); - unsigned char fix_outline_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop" - patch((void *) 0x4d830, fix_outline_patch); - overwrite_call((void *) 0x4d764, (void *) glColor4f_injection); - } -#endif - - // Fix Furnace Visual Bug - overwrite_calls((void *) FurnaceTileEntity_getLitProgress, (void *) FurnaceTileEntity_getLitProgress_injection); - - // Send the full level, not only changed chunks - if (feature_has("Send Full Level When Hosting Game", server_enabled)) { - unsigned char nop_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop" - patch((void *) 0x717c4, nop_patch); - unsigned char mov_r3_ff[4] = {0xff, 0x30, 0xa0, 0xe3}; // "mov r3, #0xff" - patch((void *) 0x7178c, mov_r3_ff); - } - - // Java Light Ramp - if (feature_has("Use Java Beta 1.3 Light Ramp", server_disabled)) { - overwrite((void *) Dimension_updateLightRamp_non_virtual, (void *) Dimension_updateLightRamp_injection); - } - - // Fix used items transferring durability - overwrite_calls((void *) Player_startUsingItem, (void *) Player_startUsingItem_injection); - overwrite_calls((void *) Player_stopUsingItem, (void *) Player_stopUsingItem_injection); - - // Fix invalid ItemInHandRenderer texture cache - if (feature_has("Disable Buggy Held Item Caching", server_disabled)) { - // This works by forcing MCPI to always use the branch that enables using the - // cache, but then patches that as well to do the opposite - uchar ensure_equal_patch[] = {0x07, 0x00, 0x57, 0xe1}; // "cmp r7, r7" - patch((void *) 0x4b938, ensure_equal_patch); - uchar set_true_patch[] = {0x01, 0x30, 0xa0, 0x03}; // "moveq r3, #0x1" - patch((void *) 0x4b93c, set_true_patch); - } - - // 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 ef0380e..5d06d6d 100644 --- a/mods/src/misc/misc.cpp +++ b/mods/src/misc/misc.cpp @@ -1,17 +1,636 @@ +#include +#include +#include +#include +#include +#include #include #include #include #include -#include +#ifndef MCPI_HEADLESS_MODE +#include +#endif #include #include +#include +#include + +#include #include #include "misc-internal.h" #include +// Heart food overlay +static int heal_amount = 0, heal_amount_drawing = 0; +static void Gui_renderHearts_injection(Gui_renderHearts_t original, Gui *gui) { + // Get heal_amount + heal_amount = heal_amount_drawing = 0; + + Inventory *inventory = gui->minecraft->player->inventory; + ItemInstance *held_ii = Inventory_getSelected(inventory); + if (held_ii) { + Item *held = Item_items[held_ii->id]; + if (held->vtable->isFood(held) && held_ii->id) { + int nutrition = ((FoodItem *) held)->nutrition; + int cur_health = gui->minecraft->player->health; + int heal_num = fmin(cur_health + nutrition, 20) - cur_health; + heal_amount = heal_amount_drawing = heal_num; + } + } + + // Call original + original(gui); +} + +#define PINK_HEART_FULL 70 +#define PINK_HEART_HALF 79 +static Gui_blit_t Gui_blit_renderHearts_original = nullptr; +static void Gui_renderHearts_GuiComponent_blit_overlay_empty_injection(Gui *gui, int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t w1, int32_t h1, int32_t w2, int32_t h2) { + // Call original + Gui_blit_renderHearts_original(gui, x1, y1, x2, y2, w1, h1, w2, h2); + // Render the overlay + if (heal_amount_drawing == 1) { + // Half heart + Gui_blit_renderHearts_original(gui, x1, y1, PINK_HEART_HALF, 0, w1, h1, w2, h2); + heal_amount_drawing = 0; + } else if (heal_amount_drawing > 0) { + // Full heart + Gui_blit_renderHearts_original(gui, x1, y1, PINK_HEART_FULL, 0, w1, h1, w2, h2); + heal_amount_drawing -= 2; + } +} + +static void Gui_renderHearts_GuiComponent_blit_overlay_hearts_injection(Gui *gui, int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t w1, int32_t h1, int32_t w2, int32_t h2) { + // Offset the overlay + if (x2 == 52) { + heal_amount_drawing += 2; + } else if (x2 == 61 && heal_amount) { + // Half heart, flipped + Gui_blit_renderHearts_original(gui, x1, y1, PINK_HEART_FULL, 0, w1, h1, w2, h2); + heal_amount_drawing += 1; + }; + // Call original + Gui_blit_renderHearts_original(gui, x1, y1, x2, y2, w1, h1, w2, h2); + heal_amount_drawing = fmin(heal_amount_drawing, heal_amount); +} + +// Classic HUD +#define DEFAULT_HUD_PADDING 2 +#define NEW_HUD_PADDING 1 +#define HUD_ELEMENT_WIDTH 82 +#define HUD_ELEMENT_HEIGHT 9 +#define TOOLBAR_HEIGHT 22 +#define SLOT_WIDTH 20 +#define DEFAULT_BUBBLES_PADDING 1 +#define NUMBER_OF_SLOTS 9 +static int use_classic_hud = 0; +static void Gui_renderHearts_GuiComponent_blit_hearts_injection(Gui *component, int32_t x_dest, int32_t y_dest, int32_t x_src, int32_t y_src, int32_t width_dest, int32_t height_dest, int32_t width_src, int32_t height_src) { + Minecraft *minecraft = component->minecraft; + x_dest -= DEFAULT_HUD_PADDING; + float width = ((float) minecraft->screen_width) * Gui_InvGuiScale; + float height = ((float) minecraft->screen_height) * Gui_InvGuiScale; + x_dest += (width - (NUMBER_OF_SLOTS * SLOT_WIDTH)) / 2; + y_dest -= DEFAULT_HUD_PADDING; + y_dest += height - HUD_ELEMENT_HEIGHT - TOOLBAR_HEIGHT - NEW_HUD_PADDING; + // Call Original Method + Gui_blit(component, x_dest, y_dest, x_src, y_src, width_dest, height_dest, width_src, height_src); +} +static void Gui_renderHearts_GuiComponent_blit_armor_injection(Gui *component, int32_t x_dest, int32_t y_dest, int32_t x_src, int32_t y_src, int32_t width_dest, int32_t height_dest, int32_t width_src, int32_t height_src) { + Minecraft *minecraft = component->minecraft; + x_dest -= DEFAULT_HUD_PADDING + HUD_ELEMENT_WIDTH; + float width = ((float) minecraft->screen_width) * Gui_InvGuiScale; + float height = ((float) minecraft->screen_height) * Gui_InvGuiScale; + x_dest += width - ((width - (NUMBER_OF_SLOTS * SLOT_WIDTH)) / 2) - HUD_ELEMENT_WIDTH; + y_dest -= DEFAULT_HUD_PADDING; + y_dest += height - HUD_ELEMENT_HEIGHT - TOOLBAR_HEIGHT - NEW_HUD_PADDING; + // Call Original Method + Gui_blit(component, x_dest, y_dest, x_src, y_src, width_dest, height_dest, width_src, height_src); +} +static void Gui_renderBubbles_GuiComponent_blit_injection(Gui *component, int32_t x_dest, int32_t y_dest, int32_t x_src, int32_t y_src, int32_t width_dest, int32_t height_dest, int32_t width_src, int32_t height_src) { + Minecraft *minecraft = component->minecraft; + x_dest -= DEFAULT_HUD_PADDING; + float width = ((float) minecraft->screen_width) * Gui_InvGuiScale; + float height = ((float) minecraft->screen_height) * Gui_InvGuiScale; + x_dest += (width - (NUMBER_OF_SLOTS * SLOT_WIDTH)) / 2; + y_dest -= DEFAULT_HUD_PADDING + DEFAULT_BUBBLES_PADDING + HUD_ELEMENT_HEIGHT; + y_dest += height - HUD_ELEMENT_HEIGHT - TOOLBAR_HEIGHT - HUD_ELEMENT_HEIGHT - NEW_HUD_PADDING; + // Call Original Method + Gui_blit(component, x_dest, y_dest, x_src, y_src, width_dest, height_dest, width_src, height_src); +} + +// Additional GUI Rendering +static int hide_chat_messages = 0; +bool is_in_chat = 0; +static int render_selected_item_text = 0; +static void Gui_renderChatMessages_injection(Gui_renderChatMessages_t original, Gui *gui, int32_t y_offset, uint32_t max_messages, bool disable_fading, Font *font) { + // Handle Classic HUD + if (use_classic_hud) { + Minecraft *minecraft = gui->minecraft; + if (!Minecraft_isCreativeMode(minecraft)) { + y_offset -= (HUD_ELEMENT_HEIGHT * 2) + NEW_HUD_PADDING; + } + } + + // Call Original Method + if (!hide_chat_messages && !is_in_chat) { + original(gui, y_offset, max_messages, disable_fading, font); + } + + // Render Selected Item Text + if (render_selected_item_text) { + // Fix GL Mode +#ifndef MCPI_HEADLESS_MODE + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); +#endif + // Calculate Selected Item Text Scale + Minecraft *minecraft = gui->minecraft; + int32_t screen_width = minecraft->screen_width; + float scale = ((float) screen_width) * Gui_InvGuiScale; + // Render Selected Item Text + Gui_renderOnSelectItemNameText(gui, (int32_t) scale, font, y_offset - 0x13); + } +} +// Reset Selected Item Text Timer On Slot Select +static uint32_t reset_selected_item_text_timer = 0; +static void Gui_tick_injection(Gui_tick_t original, Gui *gui) { + // Call Original Method + original(gui); + + // Handle Reset + if (render_selected_item_text) { + float *selected_item_text_timer = &gui->selected_item_text_timer; + if (reset_selected_item_text_timer) { + // Reset + *selected_item_text_timer = 0; + reset_selected_item_text_timer = 0; + } + } +} +// Trigger Reset Selected Item Text Timer On Slot Select +static void Inventory_selectSlot_injection(Inventory_selectSlot_t original, Inventory *inventory, int32_t slot) { + // Call Original Method + original(inventory, slot); + + // Trigger Reset Selected Item Text Timer + if (render_selected_item_text) { + reset_selected_item_text_timer = 1; + } +} + +// Translucent Toolbar +static void Gui_renderToolBar_injection(Gui_renderToolBar_t original, Gui *gui, float param_1, int32_t param_2, int32_t param_3) { + // Call Original Method +#ifndef MCPI_HEADLESS_MODE + int was_blend_enabled = glIsEnabled(GL_BLEND); + if (!was_blend_enabled) { + glEnable(GL_BLEND); + } + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); +#endif + original(gui, param_1, param_2, param_3); +#ifndef MCPI_HEADLESS_MODE + if (!was_blend_enabled) { + glDisable(GL_BLEND); + } +#endif +} +static void Gui_renderToolBar_glColor4f_injection(GLfloat red, GLfloat green, GLfloat blue, __attribute__((unused)) GLfloat alpha) { + // Fix Alpha +#ifndef MCPI_HEADLESS_MODE + glColor4f(red, green, blue, 1.0f); +#else + (void) red; + (void) green; + (void) blue; +#endif +} + +// Fix Screen Rendering When GUI is Hidden +static void Screen_render_injection(Screen_render_t original, Screen *screen, int32_t param_1, int32_t param_2, float param_3) { + // Fix +#ifndef MCPI_HEADLESS_MODE + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); +#endif + // Call Original Method + original(screen, param_1, param_2, param_3); +} + +// Sanitize Username +#define MAX_USERNAME_LENGTH 16 +static void LoginPacket_read_injection(LoginPacket_read_t original, LoginPacket *packet, RakNet_BitStream *bit_stream) { + // Call Original Method + original(packet, bit_stream); + + // Prepare + RakNet_RakString *rak_string = &packet->username; + // Get Original Username + RakNet_RakString_SharedString *shared_string = rak_string->sharedString; + char *c_str = shared_string->c_str; + // Sanitize + char *new_username = strdup(c_str); + ALLOC_CHECK(new_username); + sanitize_string(&new_username, MAX_USERNAME_LENGTH, 0); + // Set New Username + RakNet_RakString_Assign(rak_string, new_username); + // Free + free(new_username); +} + +// Fix RakNet::RakString Security Bug +// +// RakNet::RakString's format constructor is often given unsanitized user input and is never used for formatting, +// this is a massive security risk, allowing clients to run arbitrary format specifiers, this disables the +// formatting functionality. +static RakNet_RakString *RakNet_RakString_injection(RakNet_RakString *rak_string, const char *format, ...) { + // Call Original Method + return RakNet_RakString_constructor(rak_string, "%s", format); +} + +// Print Error Message If RakNet Startup Fails +static const char *RAKNET_ERROR_NAMES[] = { + "Success", + "Already Started", + "Invalid Socket Descriptors", + "Invalid Max Connections", + "Socket Family Not Supported", + "Part Already In Use", + "Failed To Bind Port", + "Failed Test Send", + "Port Cannot Be 0", + "Failed To Create Network Thread", + "Couldn't Generate GUID", + "Unknown" +}; +#ifdef MCPI_SERVER_MODE +#define PRINT_RAKNET_STARTUP_FAILURE ERR +#else +#define PRINT_RAKNET_STARTUP_FAILURE WARN +#endif +static RakNet_StartupResult RakNetInstance_host_RakNet_RakPeer_Startup_injection(RakNet_RakPeer *rak_peer, unsigned short maxConnections, unsigned char *socketDescriptors, uint32_t socketDescriptorCount, int32_t threadPriority) { + // Call Original Method + RakNet_StartupResult result = rak_peer->vtable->Startup(rak_peer, maxConnections, socketDescriptors, socketDescriptorCount, threadPriority); + + // Print Error + if (result != RAKNET_STARTED) { + PRINT_RAKNET_STARTUP_FAILURE("Failed To Start RakNet: %s", RAKNET_ERROR_NAMES[result]); + } + + // Return + return result; +} + +// Fix Bug Where RakNetInstance Starts Pinging Potential Servers Before The "Join Game" Screen Is Opened +static RakNetInstance *RakNetInstance_injection(RakNetInstance_constructor_t original, RakNetInstance *rak_net_instance) { + // Call Original Method + RakNetInstance *result = original(rak_net_instance); + // Fix + rak_net_instance->pinging_for_hosts = 0; + // Return + return result; +} + +// Close Current Screen On Death To Prevent Bugs +static void LocalPlayer_die_injection(LocalPlayer_die_t original, LocalPlayer *entity, Entity *cause) { + // Close Screen + Minecraft *minecraft = entity->minecraft; + Minecraft_setScreen(minecraft, nullptr); + + // Call Original Method + original(entity, cause); +} + +// Fix Furnace Not Checking Item Auxiliary When Inserting New Item +static int32_t FurnaceScreen_handleAddItem_injection(FurnaceScreen_handleAddItem_t original, FurnaceScreen *furnace_screen, int32_t slot, ItemInstance *item) { + // Get Existing Item + FurnaceTileEntity *tile_entity = furnace_screen->tile_entity; + ItemInstance *existing_item = tile_entity->vtable->getItem(tile_entity, slot); + + // Check Item + int valid; + if (item->id == existing_item->id && item->auxiliary == existing_item->auxiliary) { + // Item Matches, Is Valid + valid = 1; + } else { + // Item Doesn't Match, Check If Existing Item Is Empty + if ((existing_item->id | existing_item->count | existing_item->auxiliary) == 0) { + // Existing Item Is Empty, Is Valid + valid = 1; + } else { + // Existing Item Isn't Empty, Isn't Valid + valid = 0; + } + } + + // Call Original Method + if (valid) { + // Valid + return original(furnace_screen, slot, item); + } else { + // Invalid + return 0; + } +} + +// Custom Cursor Rendering +// +// The default behavior for Touch GUI is to only render the cursor when the mouse is clicking, this fixes that. +// This also makes the cursor always render if the mouse is unlocked, instead of just when there is a Screen showing. +#ifndef MCPI_HEADLESS_MODE +static void GameRenderer_render_injection(GameRenderer_render_t original, GameRenderer *game_renderer, float param_1) { + // Call Original Method + original(game_renderer, param_1); + + // Check If Cursor Should Render + if (SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_OFF) { + // Fix GL Mode + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + // Get X And Y + float x = Mouse_getX() * Gui_InvGuiScale; + float y = Mouse_getY() * Gui_InvGuiScale; + // Render Cursor + Minecraft *minecraft = game_renderer->minecraft; + Common_renderCursor(x, y, minecraft); + } +} +#endif + +// Get Real Selected Slot +int32_t misc_get_real_selected_slot(Player *player) { + // Get Selected Slot + Inventory *inventory = player->inventory; + int32_t selected_slot = inventory->selectedSlot; + + // Linked Slots + int32_t linked_slots_length = inventory->linked_slots_length; + if (selected_slot < linked_slots_length) { + int32_t *linked_slots = inventory->linked_slots; + selected_slot = linked_slots[selected_slot]; + } + + // Return + return selected_slot; +} + +#ifndef MCPI_HEADLESS_MODE +// Properly Generate Buffers +static void anGenBuffers_injection(int32_t count, uint32_t *buffers) { + glGenBuffers(count, buffers); +} +#endif + +// Fix Graphics Bug When Switching To First-Person While Sneaking +static void PlayerRenderer_render_injection(PlayerRenderer *model_renderer, Entity *entity, float param_2, float param_3, float param_4, float param_5, float param_6) { + (*HumanoidMobRenderer_render_vtable_addr)((HumanoidMobRenderer *) model_renderer, entity, param_2, param_3, param_4, param_5, param_6); + HumanoidModel *model = model_renderer->model; + model->is_sneaking = false; +} + +// Custom API Port +HOOK(bind, int, (int sockfd, const struct sockaddr *addr, socklen_t addrlen)) { + const sockaddr *new_addr = addr; + sockaddr_in in_addr = {}; + if (addr->sa_family == AF_INET) { + in_addr = *(const struct sockaddr_in *) new_addr; + if (in_addr.sin_port == ntohs(4711)) { + const char *new_port_str = getenv("MCPI_API_PORT"); + long int new_port; + if (new_port_str != nullptr && (new_port = strtol(new_port_str, nullptr, 0)) != 0L) { + in_addr.sin_port = htons(new_port); + } + } + new_addr = (const struct sockaddr *) &in_addr; + } + ensure_bind(); + return real_bind(sockfd, new_addr, addrlen); +} + +// Change Grass Color +static int32_t get_color(LevelSource *level_source, int32_t x, int32_t z) { + Biome *biome = level_source->vtable->getBiome(level_source, x, z); + if (biome == nullptr) { + return 0; + } + return biome->color; +} +#define BIOME_BLEND_SIZE 7 +static int32_t GrassTile_getColor_injection(__attribute__((unused)) Tile *tile, LevelSource *level_source, int32_t x, __attribute__((unused)) int32_t y, int32_t z) { + int r_sum = 0; + int g_sum = 0; + int b_sum = 0; + int color_sum = 0; + int x_start = x - (BIOME_BLEND_SIZE / 2); + int z_start = z - (BIOME_BLEND_SIZE / 2); + for (int x_offset = 0; x_offset < BIOME_BLEND_SIZE; x_offset++) { + for (int z_offset = 0; z_offset < BIOME_BLEND_SIZE; z_offset++) { + int32_t color = get_color(level_source, x_start + x_offset, z_start + z_offset); + r_sum += (color >> 16) & 0xff; + g_sum += (color >> 8) & 0xff; + b_sum += color & 0xff; + color_sum++; + } + } + int r_avg = r_sum / color_sum; + int g_avg = g_sum / color_sum; + int b_avg = b_sum / color_sum; + return (r_avg << 16) | (g_avg << 8) | b_avg; +} +static int32_t TallGrass_getColor_injection(TallGrass_getColor_t original, TallGrass *tile, LevelSource *level_source, int32_t x, int32_t y, int32_t z) { + int32_t original_color = original(tile, level_source, x, y, z); + if (original_color == 0x339933) { + return GrassTile_getColor_injection((Tile *) tile, level_source, x, y, z); + } else { + return original_color; + } +} + +// Generate Caves +static void RandomLevelSource_buildSurface_injection(RandomLevelSource_buildSurface_t original, RandomLevelSource *random_level_source, int32_t chunk_x, int32_t chunk_y, unsigned char *chunk_data, Biome **biomes) { + // Call Original Method + original(random_level_source, chunk_x, chunk_y, chunk_data, biomes); + + // Get Level + Level *level = random_level_source->level; + + // Get Cave Feature + LargeCaveFeature *cave_feature = &random_level_source->cave_feature; + + // Generate + cave_feature->vtable->apply(cave_feature, (ChunkSource *) random_level_source, level, chunk_x, chunk_y, chunk_data, 0); +} + +// No Block Tinting +static int32_t Tile_getColor_injection() { + return 0xffffff; +} + +// Disable Hostile AI In Creative Mode +static Entity *PathfinderMob_findAttackTarget_injection(PathfinderMob *mob) { + // Call Original Method + Entity *target = mob->vtable->findAttackTarget(mob); + + // Only modify the AI of monsters + if (mob->vtable->getCreatureBaseType(mob) != 1) { + return target; + } + + // Check If Creative Mode + if (target != nullptr && target->vtable->isPlayer(target)) { + Player *player = (Player *) target; + Inventory *inventory = player->inventory; + bool is_creative = inventory->is_creative; + if (is_creative) { + target = nullptr; + } + } + + // Return + return target; +} + +// 3D Chests +static int32_t Tile_getRenderShape_injection(Tile *tile) { + if (tile == Tile_chest) { + // Don't Render "Simple" Chest Model + return -1; + } else { + // Call Original Method + return tile->vtable->getRenderShape(tile); + } +} +static ChestTileEntity *ChestTileEntity_injection(ChestTileEntity_constructor_t original, ChestTileEntity *tile_entity) { + // Call Original Method + original(tile_entity); + + // Enable Renderer + tile_entity->renderer_id = 1; + + // Return + return tile_entity; +} +static bool is_rendering_chest = false; +static void ModelPart_render_injection(ModelPart *model_part, float scale) { + // Start + is_rendering_chest = true; + + // Call Original Method + ModelPart_render(model_part, scale); + + // Stop + is_rendering_chest = false; +} +static void Tesselator_vertexUV_injection(Tesselator_vertexUV_t original, Tesselator *tesselator, float x, float y, float z, float u, float v) { + // Fix Chest Texture + if (is_rendering_chest) { + v /= 2; + } + + // Call Original Method + original(tesselator, x, y, z, u, v); +} +static bool ChestTileEntity_shouldSave_injection(__attribute__((unused)) unsigned char *tile_entity) { + return true; +} + +// Animated 3D Chest +static ContainerMenu *ContainerMenu_injection(ContainerMenu_constructor_t original, ContainerMenu *container_menu, Container *container, int32_t param_1) { + // Call Original Method + original(container_menu, container, param_1); + + // Play Animation + ChestTileEntity *tile_entity = (ChestTileEntity *) (((unsigned char *) container) - offsetof(ChestTileEntity, container)); + bool is_client = tile_entity->is_client; + if (!is_client) { + container->vtable->startOpen(container); + } + + // Return + return container_menu; +} +static ContainerMenu *ContainerMenu_destructor_injection(ContainerMenu_destructor_complete_t original, ContainerMenu *container_menu) { + // Play Animation + Container *container = container_menu->container; + ChestTileEntity *tile_entity = (ChestTileEntity *) (((unsigned char *) container) - offsetof(ChestTileEntity, container)); + bool is_client = tile_entity->is_client; + if (!is_client) { + container->vtable->stopOpen(container); + } + + // Call Original Method + return original(container_menu); +} + +#ifndef MCPI_HEADLESS_MODE +// Custom Outline Color +static void glColor4f_injection(__attribute__((unused)) GLfloat red, __attribute__((unused)) GLfloat green, __attribute__((unused)) GLfloat blue, __attribute__((unused)) GLfloat alpha) { + // Set Color + glColor4f(0, 0, 0, 0.4); + + // Find Line Width + char *custom_line_width = getenv("MCPI_BLOCK_OUTLINE_WIDTH"); + float line_width; + if (custom_line_width != nullptr) { + // Custom + line_width = strtof(custom_line_width, nullptr); + } else { + // Guess + line_width = 2 / Gui_InvGuiScale; + } + // Clamp Line Width + float range[2]; + glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, range); + if (range[1] < line_width) { + line_width = range[1]; + } else if (range[0] > line_width) { + line_width = range[0]; + } + // Set Line Width + glLineWidth(line_width); +} +#endif + +// Fix Furnace Visual Bug +static int FurnaceTileEntity_getLitProgress_injection(FurnaceTileEntity_getLitProgress_t original, FurnaceTileEntity *furnace, int max) { + // Call Original Method + int ret = original(furnace, max); + + // Fix Bug + if (ret > max) { + ret = max; + } + + // Return + return ret; +} + +// Fix used items transferring durability +static int selected_slot = -1; +static void Player_startUsingItem_injection(Player_startUsingItem_t original, Player *self, ItemInstance *item_instance, int time) { + selected_slot = self->inventory->selectedSlot; + original(self, item_instance, time); +} +static void Player_stopUsingItem_injection(Player_stopUsingItem_t original, Player *self) { + if (selected_slot != self->inventory->selectedSlot) { + self->itemBeingUsed.id = 0; + } + original(self); +} + +// Java Light Ramp +static void Dimension_updateLightRamp_injection(Dimension *self) { + // https://github.com/ReMinecraftPE/mcpe/blob/d7a8b6baecf8b3b050538abdbc976f690312aa2d/source/world/level/Dimension.cpp#L92-L105 + for (int i = 0; i <= 15; i++) { + float f1 = 1.0f - (((float) i) / 15.0f); + self->light_ramp[i] = ((1.0f - f1) / (f1 * 3.0f + 1.0f)) * (1.0f - 0.1f) + 0.1f; + // Default Light Ramp: + // float fVar4 = 1.0 - ((float) i * 0.0625); + // self->light_ramp[i] = ((1.0 - fVar4) / (fVar4 * 3.0 + 1.0)) * 0.95 + 0.15; + } +} + // Read Asset File static AppPlatform_readAssetFile_return_value AppPlatform_readAssetFile_injection(__attribute__((unused)) AppPlatform *app_platform, std::string const& path) { // Open File @@ -20,13 +639,14 @@ static AppPlatform_readAssetFile_return_value AppPlatform_readAssetFile_injectio // Does Not Exist AppPlatform_readAssetFile_return_value ret; ret.length = -1; - ret.data = NULL; + ret.data = nullptr; return ret; } // Read File - long len = stream.tellg(); + std::streamoff len = stream.tellg(); char *buf = new char[len]; - stream.seekg(0, stream.beg); + ALLOC_CHECK(buf); + stream.seekg(0, std::ifstream::beg); stream.read(buf, len); stream.close(); // Return String @@ -37,14 +657,14 @@ static AppPlatform_readAssetFile_return_value AppPlatform_readAssetFile_injectio } // Add Missing Buttons To Pause Menu -static void PauseScreen_init_injection(PauseScreen *screen) { +static void PauseScreen_init_injection(PauseScreen_init_t original, PauseScreen *screen) { // Call Original Method - PauseScreen_init_non_virtual(screen); + original(screen); // Check If Server Minecraft *minecraft = screen->minecraft; RakNetInstance *rak_net_instance = minecraft->rak_net_instance; - if (rak_net_instance != NULL) { + if (rak_net_instance != nullptr) { if (rak_net_instance->vtable->isServer(rak_net_instance)) { // Add Button std::vector