From 7739fb6b9b8a16c4cd079ba19af41c77e16f7b6c Mon Sep 17 00:00:00 2001 From: TheBrokenRail Date: Tue, 2 Apr 2024 15:21:35 -0400 Subject: [PATCH 1/3] Update Dependency --- dependencies/symbol-processor/src | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/symbol-processor/src b/dependencies/symbol-processor/src index 225eb25..842f05a 160000 --- a/dependencies/symbol-processor/src +++ b/dependencies/symbol-processor/src @@ -1 +1 @@ -Subproject commit 225eb259fe00348044b7b9008a810204004701df +Subproject commit 842f05a288de6be14fa92f97755d2e18acb00873 From b2a7fe3eaf12f8660633a9202953f6246ccc31ec Mon Sep 17 00:00:00 2001 From: TheBrokenRail Date: Tue, 2 Apr 2024 19:22:01 -0400 Subject: [PATCH 2/3] C++-Ification! --- libreborn/include/libreborn/util.h | 7 +- mods/CMakeLists.txt | 34 +- mods/include/mods/bucket/bucket.h | 8 - mods/include/mods/chat/chat.h | 13 +- mods/include/mods/compat/compat.h | 8 - mods/include/mods/creative/creative.h | 10 +- mods/include/mods/feature/feature.h | 10 +- mods/include/mods/fps/fps.h | 8 - mods/include/mods/home/home.h | 8 - mods/include/mods/init/init.h | 10 +- mods/include/mods/input/input.h | 8 - mods/include/mods/misc/misc.h | 10 +- mods/include/mods/override/override.h | 8 - mods/include/mods/screenshot/screenshot.h | 8 - mods/include/mods/sign/sign.h | 10 +- mods/include/mods/textures/textures.h | 8 - mods/include/mods/title-screen/title-screen.h | 2 - mods/include/mods/version/version.h | 8 - mods/src/atlas/atlas.cpp | 4 +- mods/src/bucket/bucket.cpp | 12 +- mods/src/cake/cake.cpp | 2 +- mods/src/chat/chat.cpp | 10 +- mods/src/chat/ui.cpp | 4 +- mods/src/compat/{bcm_host.c => bcm_host.cpp} | 0 mods/src/compat/{compat.c => compat.cpp} | 11 +- mods/src/compat/{egl.c => egl.cpp} | 6 +- mods/src/compat/{x11.c => x11.cpp} | 2 +- mods/src/death/death.cpp | 4 +- mods/src/feature/{feature.c => feature.cpp} | 12 +- .../game-mode/{game-mode.c => game-mode.cpp} | 16 +- mods/src/home/{home.c => home.cpp} | 6 +- mods/src/init/{init.c => init.cpp} | 0 mods/src/input/{attack.c => attack.cpp} | 2 +- mods/src/input/{bow.c => bow.cpp} | 2 +- mods/src/input/drop.cpp | 6 +- mods/src/input/{misc.c => misc.cpp} | 12 +- mods/src/input/{toggle.c => toggle.cpp} | 6 +- mods/src/misc/api.cpp | 6 +- mods/src/misc/logging.cpp | 6 +- mods/src/misc/misc-internal.h | 1 - mods/src/misc/misc.c | 850 ----------------- mods/src/misc/misc.cpp | 859 +++++++++++++++++- mods/src/options/options-internal.h | 14 - mods/src/options/options.c | 125 --- mods/src/options/options.cpp | 128 ++- .../src/override/{override.c => override.cpp} | 32 +- mods/src/readdir/readdir.c | 22 - mods/src/readdir/readdir.cpp | 22 + .../{screenshot.c => screenshot.cpp} | 20 +- mods/src/server/server.cpp | 34 +- mods/src/skin/loader.cpp | 10 +- mods/src/sound/repository.cpp | 2 +- mods/src/sound/sound.cpp | 4 +- mods/src/test/{test.c => test.cpp} | 0 mods/src/textures/headless.cpp | 2 +- mods/src/textures/textures.cpp | 4 +- mods/src/title-screen/title-screen.cpp | 2 +- mods/src/touch/touch.cpp | 2 +- mods/src/version/version.cpp | 4 +- symbols/src/game/options/Options.def | 2 +- 60 files changed, 1141 insertions(+), 1305 deletions(-) rename mods/src/compat/{bcm_host.c => bcm_host.cpp} (100%) rename mods/src/compat/{compat.c => compat.cpp} (94%) rename mods/src/compat/{egl.c => egl.cpp} (97%) rename mods/src/compat/{x11.c => x11.cpp} (96%) rename mods/src/feature/{feature.c => feature.cpp} (68%) rename mods/src/game-mode/{game-mode.c => game-mode.cpp} (79%) rename mods/src/home/{home.c => home.cpp} (91%) rename mods/src/init/{init.c => init.cpp} (100%) rename mods/src/input/{attack.c => attack.cpp} (99%) rename mods/src/input/{bow.c => bow.cpp} (89%) rename mods/src/input/{misc.c => misc.cpp} (89%) rename mods/src/input/{toggle.c => toggle.cpp} (96%) delete mode 100644 mods/src/misc/misc.c delete mode 100644 mods/src/options/options-internal.h delete mode 100644 mods/src/options/options.c rename mods/src/override/{override.c => override.cpp} (77%) delete mode 100644 mods/src/readdir/readdir.c create mode 100644 mods/src/readdir/readdir.cpp rename mods/src/screenshot/{screenshot.c => screenshot.cpp} (92%) rename mods/src/test/{test.c => test.cpp} (100%) 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..af2ecc5 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); @@ -32,7 +28,3 @@ void Level_saveLevelData_injection(Level *level); 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..a110fc5 100644 --- a/mods/src/atlas/atlas.cpp +++ b/mods/src/atlas/atlas.cpp @@ -13,7 +13,7 @@ static void ItemRenderer_renderGuiItemCorrect_injection(Font *font, Textures *te // 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; @@ -91,7 +91,7 @@ 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) + // Add Better nullptr-Check (And More UI Fixes When The gui_blocks Atlas Is Disabled) overwrite_calls((void *) ItemRenderer_renderGuiItem_two, (void *) ItemRenderer_renderGuiItem_two_injection); // Disable The gui_blocks Atlas Which Contains Pre-Rendered Textures For Blocks In The Inventory diff --git a/mods/src/bucket/bucket.cpp b/mods/src/bucket/bucket.cpp index b2fa766..bea4614 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) { @@ -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; @@ -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; } } @@ -280,7 +280,7 @@ static bool is_calm_liquid(int32_t id) { static void Minecraft_handleMouseDown_injection(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; 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/chat/chat.cpp b/mods/src/chat/chat.cpp index 857e1eb..fd499b5 100644 --- a/mods/src/chat/chat.cpp +++ b/mods/src/chat/chat.cpp @@ -26,7 +26,7 @@ std::string chat_send_api_command(Minecraft *minecraft, std::string str) { 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); diff --git a/mods/src/chat/ui.cpp b/mods/src/chat/ui.cpp index 692728f..66b9b1e 100644 --- a/mods/src/chat/ui.cpp +++ b/mods/src/chat/ui.cpp @@ -95,7 +95,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(); @@ -147,7 +147,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..241ed9a 100644 --- a/mods/src/death/death.cpp +++ b/mods/src/death/death.cpp @@ -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; \ @@ -134,7 +134,7 @@ void init_death() { } // 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/game-mode/game-mode.c b/mods/src/game-mode/game-mode.cpp similarity index 79% rename from mods/src/game-mode/game-mode.c rename to mods/src/game-mode/game-mode.cpp index 44f8be7..fafb4de 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,18 +28,18 @@ 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 *self, int32_t new_game_mode) { set_is_survival(!new_game_mode); // Call Original Method - Minecraft_setIsCreativeMode(this, new_game_mode); + Minecraft_setIsCreativeMode(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) { if (is_survival) { - // SurvivalMode, Return NULL - return NULL; + // SurvivalMode, Return nullptr + return nullptr; } else { // CreatorMode, Call Original Method return Minecraft_getCreator(minecraft); @@ -50,7 +50,7 @@ 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); + set_is_survival(true); overwrite_calls((void *) Minecraft_setIsCreativeMode, (void *) Minecraft_setIsCreativeMode_injection); // Replace CreatorLevel With ServerLevel (This Fixes Beds And Mob Spawning) 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 99% rename from mods/src/input/attack.c rename to mods/src/input/attack.cpp index a981bc3..52dcdde 100644 --- a/mods/src/input/attack.c +++ b/mods/src/input/attack.cpp @@ -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 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/misc.c b/mods/src/input/misc.cpp similarity index 89% rename from mods/src/input/misc.c rename to mods/src/input/misc.cpp index ac0a57a..a437707 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,7 +38,7 @@ 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; } @@ -48,10 +48,10 @@ static int32_t InBedScreen_handleBackEvent_injection(InBedScreen *screen, bool d 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); } } @@ -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); diff --git a/mods/src/input/toggle.c b/mods/src/input/toggle.cpp similarity index 96% rename from mods/src/input/toggle.c rename to mods/src/input/toggle.cpp index cbfe1a7..e106f0d 100644 --- a/mods/src/input/toggle.c +++ b/mods/src/input/toggle.cpp @@ -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,7 +48,7 @@ static void revert_rotation(Entity *entity) { } } static int is_front_facing = 0; -static LocalPlayer *stored_player = NULL; +static LocalPlayer *stored_player = nullptr; static void GameRenderer_setupCamera_injection(GameRenderer *game_renderer, float param_1, int param_2) { // Get Objects Minecraft *minecraft = game_renderer->minecraft; diff --git a/mods/src/misc/api.cpp b/mods/src/misc/api.cpp index d947cae..0d3b4de 100644 --- a/mods/src/misc/api.cpp +++ b/mods/src/misc/api.cpp @@ -89,7 +89,7 @@ SETUP_CALLBACK(tiles_setup, void); // Handle Custom Tiles Setup Behavior static void Tile_initTiles_injection() { // Run Functions - handle_misc_tiles_setup(NULL); + handle_misc_tiles_setup(nullptr); // Call Original Method Tile_initTiles(); @@ -103,7 +103,7 @@ static void Item_initItems_injection() { Item_initItems(); // Run Functions - handle_misc_items_setup(NULL); + handle_misc_items_setup(nullptr); } // Run Functions On Language Setup @@ -114,7 +114,7 @@ static void I18n_loadLanguage_injection(AppPlatform *app, std::string language_n I18n_loadLanguage(app, language_name); // Run Functions - handle_misc_language_setup(NULL); + handle_misc_language_setup(nullptr); } // Run Functions On GUI Key Press diff --git a/mods/src/misc/logging.cpp b/mods/src/misc/logging.cpp index 7532173..baf6336 100644 --- a/mods/src/misc/logging.cpp +++ b/mods/src/misc/logging.cpp @@ -45,7 +45,7 @@ void misc_add_message(Gui *gui, const char *text) { // 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 +53,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) { @@ -99,5 +99,5 @@ void _init_misc_logging() { overwrite_calls((void *) Level_saveLevelData, (void *) 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..eac3dce 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; +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 = nullptr; +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 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 *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, nullptr); + + // 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 = 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 *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 != 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 *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 = 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 *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 true; +} + +// 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 != 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 *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; + } +} + // 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 @@ -44,7 +664,7 @@ static void PauseScreen_init_injection(PauseScreen *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