diff --git a/media-layer/core/src/media.c b/media-layer/core/src/media.c index 7f0cf10a1..49e95f3d4 100644 --- a/media-layer/core/src/media.c +++ b/media-layer/core/src/media.c @@ -155,34 +155,42 @@ static void glfw_key(__attribute__((unused)) GLFWwindow *window, int key, int sc event.key.keysym.mod = glfw_modifier_to_sdl_modifier(mods); event.key.keysym.sym = glfw_key_to_sdl_key(key); SDL_PushEvent(&event); - if (key == GLFW_KEY_BACKSPACE && !up) { - character_event('\b'); - } } } // Pass Text To Minecraft +static void codepoint_to_utf8(unsigned char *const buffer, const unsigned int code) { + // https://stackoverflow.com/a/42013433/16198887 + if (code <= 0x7f) { + buffer[0] = code; + } else if (code <= 0x7ff) { + buffer[0] = 0xc0 | (code >> 6); // 110xxxxx + buffer[1] = 0x80 | (code & 0x3f); // 10xxxxxx + } else if (code <= 0xffff) { + buffer[0] = 0xe0 | (code >> 12); // 1110xxxx + buffer[1] = 0x80 | ((code >> 6) & 0x3f); // 10xxxxxx + buffer[2] = 0x80 | (code & 0x3f); // 10xxxxxx + } else if (code <= 0x10ffff) { + buffer[0] = 0xf0 | (code >> 18); // 11110xxx + buffer[1] = 0x80 | ((code >> 12) & 0x3f); // 10xxxxxx + buffer[2] = 0x80 | ((code >> 6) & 0x3f); // 10xxxxxx + buffer[3] = 0x80 | (code & 0x3f); // 10xxxxxx + } +} static void glfw_char(__attribute__((unused)) GLFWwindow *window, unsigned int codepoint) { if (is_interactable) { - // Signs Only Accepts ASCII Characters - size_t in_size = 4; // 1 UTF-32LE Codepoint - size_t out_size = 4; // 4 ASCII Characters Max - size_t real_out_size = out_size + 1 /* NULL-terminator */; - char *output = (char *) malloc(real_out_size); - ALLOC_CHECK(output); - memset(output, 0, real_out_size); - iconv_t cd = iconv_open("ASCII//TRANSLIT", "UTF-32LE"); - if (cd != (iconv_t) -1) { - safe_iconv(cd, (char *) &codepoint, in_size, output, out_size); - iconv_close(cd); - } else { - IMPOSSIBLE(); - } - for (size_t i = 0; output[i] != '\0'; i++) { - character_event(output[i]); + // Convert + size_t str_size = 4 /* Maximum UTF-8 character size */ + 1 /* NULL-terminator */; + char str[str_size]; + memset(str, 0, str_size); + codepoint_to_utf8((unsigned char *) str, codepoint); + char *cp437_str = to_cp437(str); + // Send EventĀ· + for (int i = 0; cp437_str[i] != '\0'; i++) { + character_event(cp437_str[i]); } // Free - free(output); + free(cp437_str); } } diff --git a/mods/CMakeLists.txt b/mods/CMakeLists.txt index c63d1ebef..3b94a90c3 100644 --- a/mods/CMakeLists.txt +++ b/mods/CMakeLists.txt @@ -66,7 +66,7 @@ else() target_link_libraries(input mods-headers reborn-patch symbols creative feature misc media-layer-core) add_library(sign SHARED src/sign/sign.cpp) - target_link_libraries(sign mods-headers reborn-patch symbols feature input) + target_link_libraries(sign mods-headers reborn-patch symbols feature input media-layer-core) add_library(touch SHARED src/touch/touch.cpp) target_link_libraries(touch mods-headers reborn-patch symbols feature) diff --git a/mods/src/sign/sign.cpp b/mods/src/sign/sign.cpp index 561695a63..600743d16 100644 --- a/mods/src/sign/sign.cpp +++ b/mods/src/sign/sign.cpp @@ -1,5 +1,6 @@ #include +#include #include #include @@ -8,6 +9,16 @@ #include #include +// Handle Backspace +static int32_t sdl_key_to_minecraft_key_injection(int32_t sdl_key) { + if (sdl_key == SDLK_BACKSPACE) { + return 8; + } else { + // Call Original Method + return (*sdl_key_to_minecraft_key)(sdl_key); + } +} + // Open Sign Screen static void LocalPlayer_openTextEdit_injection(unsigned char *local_player, unsigned char *sign) { if (*(int32_t *) (sign + TileEntity_id_property_offset) == 4) { @@ -19,18 +30,10 @@ static void LocalPlayer_openTextEdit_injection(unsigned char *local_player, unsi } } -#define BACKSPACE_KEY 8 - -static int is_valid_key(char key) { - return (key >= 32 && key <= 126) || key == BACKSPACE_KEY; -} - // Store Text Input std::vector input; void sign_key_press(char key) { - if (is_valid_key(key)) { - input.push_back(key); - } + input.push_back(key); } static void clear_input(__attribute__((unused)) unsigned char *minecraft) { input.clear(); @@ -41,16 +44,11 @@ static void TextEditScreen_updateEvents_injection(unsigned char *screen) { // Call Original Method (*Screen_updateEvents)(screen); - if (*(char *)(screen + 4) == '\0') { + if (!*(bool *)(screen + Screen_passthrough_input_property_offset)) { unsigned char *vtable = *(unsigned char **) screen; for (char key : input) { - if (key == BACKSPACE_KEY) { - // Handle Backspace - (*(Screen_keyPressed_t *) (vtable + Screen_keyPressed_vtable_offset))(screen, BACKSPACE_KEY); - } else { - // Handle Normal Key - (*(Screen_keyboardNewChar_t *) (vtable + Screen_keyboardNewChar_vtable_offset))(screen, key); - } + // Handle Normal Key + (*(Screen_keyboardNewChar_t *) (vtable + Screen_keyboardNewChar_vtable_offset))(screen, key); } } clear_input(NULL); @@ -59,10 +57,12 @@ static void TextEditScreen_updateEvents_injection(unsigned char *screen) { // Init void init_sign() { if (feature_has("Fix Sign Placement", server_disabled)) { + // Handle Backspace + overwrite_calls((void *) sdl_key_to_minecraft_key, (void *) sdl_key_to_minecraft_key_injection); // Fix Signs patch_address(LocalPlayer_openTextEdit_vtable_addr, (void *) LocalPlayer_openTextEdit_injection); patch_address(TextEditScreen_updateEvents_vtable_addr, (void *) TextEditScreen_updateEvents_injection); - // Clear input On Input Tick + // Clear Input On Input Tick input_run_on_tick(clear_input); } } diff --git a/symbols/include/symbols/minecraft.h b/symbols/include/symbols/minecraft.h index f4a065e41..1eab67e3c 100644 --- a/symbols/include/symbols/minecraft.h +++ b/symbols/include/symbols/minecraft.h @@ -18,6 +18,9 @@ static renderCursor_t renderCursor = (renderCursor_t) 0x480c4; typedef void (*sleepMs_t)(int32_t x); static sleepMs_t sleepMs = (sleepMs_t) 0x13cf4; +typedef int32_t (*sdl_key_to_minecraft_key_t)(int32_t sdl_key); +static sdl_key_to_minecraft_key_t sdl_key_to_minecraft_key = (sdl_key_to_minecraft_key_t) 0x1243c; + static char **default_path = (char **) 0xe264; // /.minecraft/ static char **default_username = (char **) 0x18fd4; // StevePi static char **minecraft_pi_version = (char **) 0x39d94; // v0.1.1 alpha @@ -554,6 +557,7 @@ static uint32_t Screen_rendered_buttons_property_offset = 0x18; // std::vector static uint32_t Screen_width_property_offset = 0x8; // int32_t static uint32_t Screen_height_property_offset = 0xc; // int32_t +static uint32_t Screen_passthrough_input_property_offset = 0x10; // bool // Button