From 032490c7b2e98cba1f86fb95eb8305eecf756d56 Mon Sep 17 00:00:00 2001 From: TheBrokenRail Date: Tue, 16 Feb 2021 12:26:40 -0500 Subject: [PATCH] Add Chat --- .gitignore | 3 +- Dockerfile.client | 2 +- libreborn/include/libreborn/libreborn.h | 7 ++ libreborn/include/libreborn/minecraft.h | 32 ++++++- mods/CMakeLists.txt | 9 +- mods/src/camera/camera.cpp | 1 + mods/src/chat/chat.cpp | 108 ++++++++++++++++++++++++ mods/src/chat/chat.h | 13 +++ mods/src/chat/ui.c | 95 +++++++++++++++++++++ mods/src/compat/compat.c | 15 ++++ mods/src/game_mode/game_mode.cpp | 2 + mods/src/init/init.c | 1 + mods/src/init/init.h | 1 + mods/src/input/input.c | 4 + mods/src/input/input.cpp | 1 + mods/src/misc/misc.cpp | 15 ++++ mods/src/override/override.c | 3 + mods/src/screenshot/screenshot.c | 4 + mods/src/server/server.cpp | 18 +--- mods/src/test/test.c | 1 + mods/src/textures/textures.cpp | 2 + scripts/package.sh | 5 +- 22 files changed, 320 insertions(+), 22 deletions(-) create mode 100644 mods/src/chat/chat.cpp create mode 100644 mods/src/chat/chat.h create mode 100644 mods/src/chat/ui.c diff --git a/.gitignore b/.gitignore index ac82e380..df22795e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /out -/debian/tmp \ No newline at end of file +/debian/tmp +/.vscode \ No newline at end of file diff --git a/Dockerfile.client b/Dockerfile.client index b239150d..fd80ed2a 100644 --- a/Dockerfile.client +++ b/Dockerfile.client @@ -5,7 +5,7 @@ ENV DEBIAN_FRONTEND noninteractive RUN \ # Install Runtime Dependencies apt-get update && \ - apt-get install -y --no-install-recommends tini libgles1 libx11-6 libsdl1.2debian zlib1g libfreeimage3 libglfw3 xinput libxfixes3 gosu && \ + apt-get install -y --no-install-recommends tini libgles1 libx11-6 libsdl1.2debian zlib1g libfreeimage3 libglfw3 xinput libxfixes3 gosu tk && \ rm -rf /var/lib/apt/lists/* # Compile Environment diff --git a/libreborn/include/libreborn/libreborn.h b/libreborn/include/libreborn/libreborn.h index 0f84247d..a220b30a 100644 --- a/libreborn/include/libreborn/libreborn.h +++ b/libreborn/include/libreborn/libreborn.h @@ -8,9 +8,16 @@ extern "C" { #include #include +// Logging #define INFO(msg, ...) fprintf(stderr, "[INFO]: " msg "\n", __VA_ARGS__); #define ERR(msg, ...) fprintf(stderr, "[ERR]: " msg "\n", __VA_ARGS__); exit(EXIT_FAILURE); +// Check Memory Allocation +#define ALLOC_CHECK(obj) if (obj == NULL) { ERR("(%s:%i) Memory Allocation Failed", __FILE__, __LINE__); } + +// Set obj To NULL On asprintf() Failure +#define asprintf(obj, ...) if (asprintf(obj, __VA_ARGS__) == -1) { *obj = NULL; } + #define HOOK(name, return_type, args) \ typedef return_type (*name##_t)args; \ static name##_t real_##name = NULL; \ diff --git a/libreborn/include/libreborn/minecraft.h b/libreborn/include/libreborn/minecraft.h index 85e655f8..d656c540 100644 --- a/libreborn/include/libreborn/minecraft.h +++ b/libreborn/include/libreborn/minecraft.h @@ -102,6 +102,15 @@ static uint32_t Minecraft_player_property_offset = 0x18c; // LocalPlayer * static uint32_t Minecraft_options_property_offset = 0x3c; // Options static uint32_t Minecraft_hit_result_property_offset = 0xc38; // HitResult static uint32_t Minecraft_progress_property_offset = 0xc60; // int32_t +static uint32_t Minecraft_command_server_property_offset = 0xcc0; // CommandServer * + +// CommandServer + +static uint32_t CommandServer_minecraft_property_offset = 0x18; // Minecraft * + +// ChatPacket + +static uint32_t ChatPacket_message_property_offset = 0xc; // char * // HitResult @@ -245,6 +254,12 @@ static FillingContainer_addItem_t FillingContainer_addItem = (FillingContainer_a // RakNetInstance +typedef void (*RakNetInstance_send_t)(unsigned char *rak_net_instance, unsigned char *packet); +static uint32_t RakNetInstance_send_vtable_offset = 0x38; + +typedef uint32_t (*RakNetInstance_isServer_t)(unsigned char *rak_net_instance); +static uint32_t RakNetInstance_isServer_vtable_offset = 0x48; + static uint32_t RakNetInstance_peer_property_offset = 0x4; // RakNet::RakPeer @@ -261,6 +276,8 @@ static void *ServerSideNetworkHandler_onDisconnect_vtable_addr = (void *) 0x109b typedef unsigned char *(*ServerSideNetworkHandler_getPlayer_t)(unsigned char *server_side_network_handler, unsigned char *guid); static ServerSideNetworkHandler_getPlayer_t ServerSideNetworkHandler_getPlayer = (ServerSideNetworkHandler_getPlayer_t) 0x75464; +static void *ServerSideNetworkHandler_handle_ChatPacket_vtable_addr = (void *) 0x109c60; + // Entity typedef void (*Entity_die_t)(unsigned char *entity, unsigned char *cause); @@ -300,6 +317,14 @@ static ItemRenderer_renderGuiItemCorrect_t ItemRenderer_renderGuiItemCorrect = ( #include +// Structures + +struct ConnectedClient { + uint32_t sock; + std::string str; + long time; +}; + // AppPlatform typedef void (*AppPlatform_saveScreenshot_t)(unsigned char *app_platform, std::string const& param1, std::string const& param_2); @@ -320,6 +345,11 @@ static Minecraft_selectLevel_t Minecraft_selectLevel = (Minecraft_selectLevel_t) typedef void (*Minecraft_leaveGame_t)(unsigned char *minecraft, bool save_remote_level); static Minecraft_leaveGame_t Minecraft_leaveGame = (Minecraft_leaveGame_t) 0x15ea0; +// CommandServer + +typedef std::string (*CommandServer_parse_t)(unsigned char *command_server, struct ConnectedClient &client, std::string const& command); +static CommandServer_parse_t CommandServer_parse = (CommandServer_parse_t) 0x6aa8c; + // Level typedef void (*Level_addParticle_t)(unsigned char *level, std::string const& particle, float x, float y, float z, float deltaX, float deltaY, float deltaZ, int count); @@ -340,7 +370,7 @@ static Textures_tick_t Textures_tick = (Textures_tick_t) 0x531c4; // RakNet::RakPeer -typedef bool (*RakNet_RakPeer_IsBanned_t)(unsigned char *rakpeer, const char *ip); +typedef bool (*RakNet_RakPeer_IsBanned_t)(unsigned char *rak_peer, const char *ip); static RakNet_RakPeer_IsBanned_t RakNet_RakPeer_IsBanned = (RakNet_RakPeer_IsBanned_t) 0xda3b4; // RakNet::SystemAddress diff --git a/mods/CMakeLists.txt b/mods/CMakeLists.txt index a10ec870..a284c08e 100644 --- a/mods/CMakeLists.txt +++ b/mods/CMakeLists.txt @@ -41,7 +41,7 @@ add_library(game_mode SHARED src/game_mode/game_mode.c src/game_mode/game_mode.c target_link_libraries(game_mode reborn) add_library(input SHARED src/input/input.c src/input/input.cpp) -target_link_libraries(input reborn feature SDL) +target_link_libraries(input reborn feature SDL chat) add_library(misc SHARED src/misc/misc.c src/misc/misc.cpp) target_link_libraries(misc reborn feature util) @@ -55,11 +55,14 @@ target_link_libraries(override reborn dl) add_library(textures SHARED src/textures/textures.cpp) target_link_libraries(textures reborn feature GLESv1_CM) +add_library(chat SHARED src/chat/chat.cpp src/chat/ui.c) +target_link_libraries(chat reborn pthread) + add_library(test SHARED src/test/test.c) target_link_libraries(test reborn) add_library(init SHARED src/init/init.c) -target_link_libraries(init compat server game_mode camera input misc options textures test) +target_link_libraries(init compat server game_mode camera input misc options textures chat test) ## Stubs @@ -76,4 +79,4 @@ target_link_libraries(GLESv2 GLESv1_CM) target_link_options(GLESv2 PRIVATE "-Wl,--no-as-needed") ## Install -install(TARGETS init compat readdir feature screenshot override server game_mode camera input misc options textures test bcm_host EGL GLESv2 DESTINATION /mods) \ No newline at end of file +install(TARGETS init compat readdir feature screenshot override server game_mode camera input misc options textures chat test bcm_host EGL GLESv2 DESTINATION /mods) \ No newline at end of file diff --git a/mods/src/camera/camera.cpp b/mods/src/camera/camera.cpp index 9a0e27e9..6246b538 100644 --- a/mods/src/camera/camera.cpp +++ b/mods/src/camera/camera.cpp @@ -17,6 +17,7 @@ static unsigned char *EntityRenderDispatcher_injection(unsigned char *dispatcher // Register TripodCameraRenderer unsigned char *renderer = (unsigned char *) ::operator new(TRIPOD_CAMERA_RENDERER_SIZE); + ALLOC_CHECK(renderer); (*TripodCameraRenderer)(renderer); (*EntityRenderDispatcher_assign)(dispatcher, (unsigned char) 0x5, renderer); diff --git a/mods/src/chat/chat.cpp b/mods/src/chat/chat.cpp new file mode 100644 index 00000000..e3e1e889 --- /dev/null +++ b/mods/src/chat/chat.cpp @@ -0,0 +1,108 @@ +#include +#include +#include +#include + +#include +#include + +#include "../init/init.h" + +#include "chat.h" + +// Send API Command +static void send_api_command(unsigned char *minecraft, char *str) { + struct ConnectedClient client; + client.sock = -1; + client.str = ""; + client.time = 0; + unsigned char *command_server = *(unsigned char **) (minecraft + Minecraft_command_server_property_offset); + if (command_server != NULL) { + (*CommandServer_parse)(command_server, client, str); + } +} +// Send API Chat Command +static void send_api_chat_command(unsigned char *minecraft, char *str) { + char *command = NULL; + asprintf(&command, "chat.post(%s)\n", str); + ALLOC_CHECK(command); + send_api_command(minecraft, command); + free(command); +} + +// Send Message To Players +static void send_message(unsigned char *server_side_network_handler, char *username, char *message) { + char *full_message = NULL; + asprintf(&full_message, "<%s> %s", username, message); + ALLOC_CHECK(full_message); + (*ServerSideNetworkHandler_displayGameMessage)(server_side_network_handler, std::string(full_message)); + free(full_message); +} + +// Manually Send (And Loopback) ChatPacket +static void CommandServer_parse_CommandServer_dispatchPacket_injection(unsigned char *command_server, unsigned char *packet) { + unsigned char *minecraft = *(unsigned char **) (command_server + CommandServer_minecraft_property_offset); + if (minecraft != NULL) { + unsigned char *rak_net_instance = *(unsigned char **) (minecraft + Minecraft_rak_net_instance_property_offset); + unsigned char *rak_net_instance_vtable = *(unsigned char **) rak_net_instance; + RakNetInstance_isServer_t RakNetInstance_isServer = *(RakNetInstance_isServer_t *) (rak_net_instance_vtable + RakNetInstance_isServer_vtable_offset); + if ((*RakNetInstance_isServer)(rak_net_instance)) { + // Hosting Multiplayer + char *message = *(char **) (packet + ChatPacket_message_property_offset); + unsigned char *server_side_network_handler = *(unsigned char **) (minecraft + Minecraft_server_side_network_handler_property_offset); + send_message(server_side_network_handler, *default_username, message); + } else { + // Client + RakNetInstance_send_t RakNetInstance_send = *(RakNetInstance_send_t *) (rak_net_instance_vtable + RakNetInstance_send_vtable_offset); + (*RakNetInstance_send)(rak_net_instance, packet); + } + } +} + +// Handle ChatPacket Server-Side +static void ServerSideNetworkHandler_handle_ChatPacket_injection(unsigned char *server_side_network_handler, unsigned char *rak_net_guid, unsigned char *chat_packet) { + unsigned char *player = (*ServerSideNetworkHandler_getPlayer)(server_side_network_handler, rak_net_guid); + if (player != NULL) { + char *username = *(char **) (player + Player_username_property_offset); + char *message = *(char **) (chat_packet + ChatPacket_message_property_offset); + send_message(server_side_network_handler, username, message); + } +} + +// Message Queue +static pthread_mutex_t queue_mutex = PTHREAD_MUTEX_INITIALIZER; +static std::vector queue; +// Add To Queue +void chat_queue_message(char *message) { + // Lock + pthread_mutex_lock(&queue_mutex); + // Add + std::string str; + str.append(message); + queue.push_back(str); + // Unlock + pthread_mutex_unlock(&queue_mutex); +} +// Empty Queue +void chat_send_messages(unsigned char *minecraft) { + // Lock + pthread_mutex_lock(&queue_mutex); + // Loop + for (unsigned int i = 0; i < queue.size(); i++) { + send_api_chat_command(minecraft, (char *) queue[i].c_str()); + } + queue.clear(); + // Unlock + pthread_mutex_unlock(&queue_mutex); +} + +// Init +void init_chat() { + // Disable Original ChatPacket Loopback + unsigned char disable_chat_packet_loopback_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; + patch((void *) 0x6b490, disable_chat_packet_loopback_patch); + // 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); +} \ No newline at end of file diff --git a/mods/src/chat/chat.h b/mods/src/chat/chat.h new file mode 100644 index 00000000..5b931999 --- /dev/null +++ b/mods/src/chat/chat.h @@ -0,0 +1,13 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +void chat_open(); +void chat_queue_message(char *message); +void chat_send_messages(unsigned char *minecraft); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/mods/src/chat/ui.c b/mods/src/chat/ui.c new file mode 100644 index 00000000..b2209471 --- /dev/null +++ b/mods/src/chat/ui.c @@ -0,0 +1,95 @@ +#define _GNU_SOURCE + +#include +#include +#include +#include + +#include + +#include "chat.h" + +#define CHAT_WINDOW_TCL \ + "set message \"\"\n" \ + "proc submit {} {\n" \ + "global message\n" \ + "puts \"$message\"\n" \ + "exit\n" \ + "}\n" \ + \ + "wm resizable . false false\n" \ + "wm title . \"Chat\"\n" \ + "wm attributes . -topmost true -type {dialog}\n" \ + \ + "ttk::label .label -text \"Enter Chat Message:\"\n" \ + \ + "ttk::entry .entry -textvariable message\n" \ + "focus .entry\n" \ + "bind .entry submit\n" \ + \ + "ttk::frame .button\n" \ + "ttk::button .button.submit -text \"Submit\" -command submit\n" \ + "ttk::button .button.cancel -text \"Cancel\" -command exit\n" \ + \ + "grid .label -row 0 -padx 6 -pady 6\n" \ + "grid .entry -row 1 -padx 6\n" \ + "grid .button -row 2 -padx 3 -pady 6\n" \ + "grid .button.cancel -row 0 -column 0 -padx 3\n" \ + "grid .button.submit -row 0 -column 1 -padx 3\n" + +// Run Command +static char *run_command(char *command, int *return_code) { + // Don't Contaminate Child Process + unsetenv("LD_LIBRARY_PATH"); + unsetenv("LD_PRELOAD"); + + // Start + FILE *out = popen(command, "r"); + if (!out) { + ERR("%s", "Failed To Run Command"); + } + + // Record + char *output = NULL; + int c; + while ((c = fgetc(out)) != EOF) { + asprintf(&output, "%s%c", output == NULL ? "" : output, (char) c); + ALLOC_CHECK(output); + } + + // Return + *return_code = pclose(out); + return output; +} + +// Chat Thread +static void *chat_thread(__attribute__((unused)) void *nop) { + // Prepare + setenv("CHAT_WINDOW_TCL", CHAT_WINDOW_TCL, 1); + // Open + int return_code; + char *output = run_command("echo \"${CHAT_WINDOW_TCL}\" | wish -name \"Minecraft - Pi edition\"", &return_code); + // Handle Message + if (output != NULL) { + if (return_code == 0) { + // Remove Ending Newline + int length = strlen(output); + if (output[length - 1] == '\n') { + output[length - 1] = '\0'; + } + length = strlen(output); + // Submit + chat_queue_message(output); + } + // Free + free(output); + } + // Return + return NULL; +} + +// Create Chat Thead +void chat_open() { + pthread_t thread; + pthread_create(&thread, NULL, chat_thread, NULL); +} \ No newline at end of file diff --git a/mods/src/compat/compat.c b/mods/src/compat/compat.c index 3e822be7..7a5b7f39 100644 --- a/mods/src/compat/compat.c +++ b/mods/src/compat/compat.c @@ -19,6 +19,7 @@ #include "../feature/feature.h" #include "../input/input.h" #include "../screenshot/screenshot.h" +#include "../chat/chat.h" #include "../init/init.h" #include "compat.h" @@ -99,6 +100,9 @@ static SDLKey glfw_key_to_sdl_key(int key) { // Third Person case GLFW_KEY_F5: return SDLK_F5; + // Chat + case GLFW_KEY_T: + return SDLK_t; // Unknown default: return SDLK_UNKNOWN; @@ -189,6 +193,8 @@ HOOK(SDL_WM_SetCaption, void, (const char *title, __attribute__((unused)) const glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 1); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + // Extra Settings + glfwWindowHint(GLFW_AUTO_ICONIFY, GLFW_FALSE); glfw_window = glfwCreateWindow(DEFAULT_WIDTH, DEFAULT_HEIGHT, title, NULL, NULL); if (!glfw_window) { @@ -274,6 +280,15 @@ HOOK(SDL_PollEvent, int, (SDL_Event *event)) { } else if (event->key.keysym.sym == SDLK_F5) { input_third_person(); handled = 1; + } else if (event->key.keysym.sym == SDLK_t) { + // Release Mouse Immediately + SDL_WM_GrabInput(SDL_GRAB_OFF); + // Stop Tracking Mouse + glfw_key(glfw_window, GLFW_KEY_TAB, -1, GLFW_PRESS, -1); + glfw_key(glfw_window, GLFW_KEY_TAB, -1, GLFW_RELEASE, -1); + // Open Chat + chat_open(); + handled = 1; } } else if (event->type == SDL_MOUSEBUTTONDOWN || event->type == SDL_MOUSEBUTTONUP) { if (event->button.button == SDL_BUTTON_RIGHT) { diff --git a/mods/src/game_mode/game_mode.cpp b/mods/src/game_mode/game_mode.cpp index 7ef86b82..4b1f3193 100644 --- a/mods/src/game_mode/game_mode.cpp +++ b/mods/src/game_mode/game_mode.cpp @@ -18,6 +18,7 @@ static void SelectWorldScreen_tick_injection(unsigned char *screen) { std::string new_name = (*SelectWorldScreen_getUniqueLevelName)(screen, WORLD_NAME); // Create SimpleLevelChooseScreen unsigned char *new_screen = (unsigned char *) ::operator new(SIMPLE_LEVEL_CHOOSE_SCREEN_SIZE); + ALLOC_CHECK(new_screen); (*SimpleChooseLevelScreen)(new_screen, new_name); // Set Screen unsigned char *minecraft = get_minecraft_from_screen(screen); @@ -35,6 +36,7 @@ static void Touch_SelectWorldScreen_tick_injection(unsigned char *screen) { std::string new_name = (*Touch_SelectWorldScreen_getUniqueLevelName)(screen, WORLD_NAME); // Create SimpleLevelChooseScreen unsigned char *new_screen = (unsigned char *) ::operator new(SIMPLE_LEVEL_CHOOSE_SCREEN_SIZE); + ALLOC_CHECK(new_screen); (*SimpleChooseLevelScreen)(new_screen, new_name); // Set Screen unsigned char *minecraft = get_minecraft_from_screen(screen); diff --git a/mods/src/init/init.c b/mods/src/init/init.c index 610958a1..c717c1c2 100644 --- a/mods/src/init/init.c +++ b/mods/src/init/init.c @@ -10,4 +10,5 @@ __attribute__((constructor)) static void init() { init_camera(); init_options(); init_textures(); + init_chat(); } \ No newline at end of file diff --git a/mods/src/init/init.h b/mods/src/init/init.h index d986e7c9..b478a794 100644 --- a/mods/src/init/init.h +++ b/mods/src/init/init.h @@ -13,6 +13,7 @@ void init_misc(); void init_camera(); void init_options(); void init_textures(); +void init_chat(); #ifdef __cplusplus } diff --git a/mods/src/input/input.c b/mods/src/input/input.c index f7a6b149..fffc61df 100644 --- a/mods/src/input/input.c +++ b/mods/src/input/input.c @@ -3,6 +3,7 @@ #include "../feature/feature.h" #include "input.h" #include "../init/init.h" +#include "../chat/chat.h" #include @@ -57,6 +58,9 @@ static void Minecraft_tickInput_injection(unsigned char *minecraft) { *(options + Options_third_person_property_offset) = *(options + Options_third_person_property_offset) ^ 1; } third_person_toggle = 0; + + // Send Queued Chat Message + chat_send_messages(minecraft); } #include diff --git a/mods/src/input/input.cpp b/mods/src/input/input.cpp index f539cbd0..1e02d06c 100644 --- a/mods/src/input/input.cpp +++ b/mods/src/input/input.cpp @@ -12,6 +12,7 @@ static void LocalPlayer_openTextEdit_injection(unsigned char *local_player, unsi if (*(int32_t *) (sign + TileEntity_id_property_offset) == 4) { unsigned char *minecraft = *(unsigned char **) (local_player + LocalPlayer_minecraft_property_offset); unsigned char *screen = (unsigned char *) ::operator new(TEXT_EDIT_SCREEN_SIZE); + ALLOC_CHECK(screen); screen = (*TextEditScreen)(screen, sign); (*Minecraft_setScreen)(minecraft, screen); } diff --git a/mods/src/misc/misc.cpp b/mods/src/misc/misc.cpp index 44e9f31f..0d39ecd4 100644 --- a/mods/src/misc/misc.cpp +++ b/mods/src/misc/misc.cpp @@ -27,10 +27,12 @@ static AppPlatform_readAssetFile_return_value AppPlatform_readAssetFile_injectio static void inventory_add_item(unsigned char *inventory, unsigned char *item, bool is_tile) { unsigned char *item_instance = (unsigned char *) ::operator new(ITEM_INSTANCE_SIZE); + ALLOC_CHECK(item_instance); item_instance = (*(is_tile ? ItemInstance_constructor_tile : ItemInstance_constructor_item))(item_instance, item); (*FillingContainer_addItem)(inventory, item_instance); } +// Expand Creative Inventory static int32_t Inventory_setupDefault_FillingContainer_addItem_call_injection(unsigned char *filling_container, unsigned char *item_instance) { // Call Original int32_t ret = (*FillingContainer_addItem)(filling_container, item_instance); @@ -46,6 +48,7 @@ static int32_t Inventory_setupDefault_FillingContainer_addItem_call_injection(un continue; } unsigned char *item_instance = (unsigned char *) ::operator new(ITEM_INSTANCE_SIZE); + ALLOC_CHECK(item_instance); item_instance = (*ItemInstance_constructor_item_extra)(item_instance, *Item_dye_powder, 1, i); (*FillingContainer_addItem)(filling_container, item_instance); } @@ -96,6 +99,15 @@ static void Inventory_selectSlot_injection(unsigned char *inventory, int32_t slo reset_selected_item_text_timer = true; } +// Print Chat To Log +static void Gui_addMessage_injection(unsigned char *gui, std::string const& text) { + // Print Log Message + fprintf(stderr, "[CHAT]: %s\n", text.c_str()); + + // Call Original Method + (*Gui_addMessage)(gui, text); +} + void init_misc_cpp() { // Implement AppPlatform::readAssetFile So Translations Work overwrite((void *) AppPlatform_readAssetFile, (void *) AppPlatform_readAssetFile_injection); @@ -109,4 +121,7 @@ void init_misc_cpp() { 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); + + // Print Chat To Log + overwrite_calls((void *) Gui_addMessage, (void *) Gui_addMessage_injection); } \ No newline at end of file diff --git a/mods/src/override/override.c b/mods/src/override/override.c index 4b320809..b585020d 100644 --- a/mods/src/override/override.c +++ b/mods/src/override/override.c @@ -18,10 +18,12 @@ static char *get_override_path(const char *filename) { // Get Asset Override Path char *overrides = NULL; asprintf(&overrides, "%s/.minecraft-pi/overrides", getenv("HOME")); + ALLOC_CHECK(overrides); // Get data Path char *data = NULL; char *cwd = getcwd(NULL, 0); asprintf(&data, "%s/data", cwd); + ALLOC_CHECK(data); free(cwd); // Get Full Path char *new_path = NULL; @@ -29,6 +31,7 @@ static char *get_override_path(const char *filename) { if (full_path != NULL) { if (starts_with(full_path, data)) { asprintf(&new_path, "%s%s", overrides, &full_path[strlen(data)]); + ALLOC_CHECK(new_path); if (access(new_path, F_OK) == -1) { free(new_path); new_path = NULL; diff --git a/mods/src/screenshot/screenshot.c b/mods/src/screenshot/screenshot.c index 9626c286..36ed467d 100644 --- a/mods/src/screenshot/screenshot.c +++ b/mods/src/screenshot/screenshot.c @@ -31,12 +31,15 @@ void take_screenshot() { char *screenshots = NULL; asprintf(&screenshots, "%s/.minecraft-pi/screenshots", getenv("HOME")); + ALLOC_CHECK(screenshots); int num = 1; char *file = NULL; asprintf(&file, "%s/%s.png", screenshots, time); + ALLOC_CHECK(file); while (access(file, F_OK) != -1) { asprintf(&file, "%s/%s-%i.png", screenshots, time, num); + ALLOC_CHECK(file); num++; } @@ -84,6 +87,7 @@ __attribute__((constructor)) static void init() { // Screenshots Folder char *screenshots_folder = NULL; asprintf(&screenshots_folder, "%s/.minecraft-pi/screenshots", getenv("HOME")); + ALLOC_CHECK(screenshots_folder); { // Check Screenshots Folder struct stat obj; diff --git a/mods/src/server/server.cpp b/mods/src/server/server.cpp index 3bdc4bbb..aa4bd2f7 100644 --- a/mods/src/server/server.cpp +++ b/mods/src/server/server.cpp @@ -53,11 +53,8 @@ static void *read_stdin_thread(__attribute__((unused)) void *data) { } stdin_buffer_complete = true; } else { - if (stdin_buffer == NULL) { - asprintf((char **) &stdin_buffer, "%c", (char) x); - } else { - asprintf((char **) &stdin_buffer, "%s%c", stdin_buffer, (char) x); - } + asprintf((char **) &stdin_buffer, "%s%c", stdin_buffer == NULL ? "" : stdin_buffer, (char) x); + ALLOC_CHECK(stdin_buffer); } } } @@ -87,6 +84,7 @@ static void start_world(unsigned char *minecraft) { INFO("Listening On: %i", port); void *screen = ::operator new(PROGRESS_SCREEN_SIZE); + ALLOC_CHECK(screen); screen = (*ProgressScreen)((unsigned char *) screen); (*Minecraft_setScreen)(minecraft, (unsigned char *) screen); } @@ -348,14 +346,6 @@ static void Minecraft_update_injection(unsigned char *minecraft) { handle_server_stop(minecraft); } -static void Gui_addMessage_injection(unsigned char *gui, std::string const& text) { - // Print Log Message - fprintf(stderr, "[CHAT]: %s\n", text.c_str()); - - // Call Original Method - (*Gui_addMessage)(gui, text); -} - static bool RakNet_RakPeer_IsBanned_injection(__attribute__((unused)) unsigned char *rakpeer, const char *ip) { // Check banned-ips.txt std::string banned_ips_file_path = get_banned_ips_file(); @@ -483,8 +473,6 @@ static void server_init() { // Exit handler signal(SIGINT, exit_handler); signal(SIGTERM, exit_handler); - // Print Chat To Log - overwrite_calls((void *) Gui_addMessage, (void *) Gui_addMessage_injection); // Set Max Players unsigned char max_players_patch[4] = {get_max_players(), 0x30, 0xa0, 0xe3}; patch((void *) 0x166d0, max_players_patch); diff --git a/mods/src/test/test.c b/mods/src/test/test.c index 621faadb..04af386b 100644 --- a/mods/src/test/test.c +++ b/mods/src/test/test.c @@ -48,6 +48,7 @@ void run_tests() { { char *path = NULL; asprintf(&path, "%s/.minecraft-pi", getenv("HOME")); + ALLOC_CHECK(path); int ret = access(path, R_OK | W_OK); free(path); diff --git a/mods/src/textures/textures.cpp b/mods/src/textures/textures.cpp index 8fd87cab..b67ccbda 100644 --- a/mods/src/textures/textures.cpp +++ b/mods/src/textures/textures.cpp @@ -30,9 +30,11 @@ static float ItemRenderer_renderGuiItemCorrect_injection(unsigned char *font, un int32_t auxilary = *(int32_t *) (item_instance + ItemInstance_auxilary_property_offset); if (id == leaves_id) { carried_item_instance = (unsigned char *) ::operator new(ITEM_INSTANCE_SIZE); + ALLOC_CHECK(carried_item_instance); (*ItemInstance_constructor_tile_extra)(carried_item_instance, *Tile_leaves_carried, count, auxilary); } else if (id == grass_id) { carried_item_instance = (unsigned char *) ::operator new(ITEM_INSTANCE_SIZE); + ALLOC_CHECK(carried_item_instance); (*ItemInstance_constructor_tile_extra)(carried_item_instance, *Tile_grass_carried, count, auxilary); } } diff --git a/scripts/package.sh b/scripts/package.sh index f89dfb8a..7dd16f87 100755 --- a/scripts/package.sh +++ b/scripts/package.sh @@ -22,9 +22,12 @@ mkdir -p out/deb rm -rf debian/tmp mkdir debian/tmp +# Version Time +DEB_VERSION_TIME="$(date --utc '+%Y%m%d.%H%M')" + # Prepare DEBIAN/control prepare_control() { - sed -i 's/${VERSION}/'"${DEB_VERSION}.$(date --utc '+%Y%m%d.%H%M')"'/g' "$1/DEBIAN/control" + sed -i 's/${VERSION}/'"${DEB_VERSION}.${DEB_VERSION_TIME}"'/g' "$1/DEBIAN/control" sed -i 's/${DEPENDENCIES}/'"${COMMON_DEPENDENCIES}$2"'/g' "$1/DEBIAN/control" sed -i 's/${RECOMMENDED_DEPENDENCIES}/'"${RECOMMENDED_DEPENDENCIES}$2"'/g' "$1/DEBIAN/control" }