Fix Signs With CP-437

This commit is contained in:
TheBrokenRail 2022-07-30 23:52:50 -04:00
parent c11c7203ef
commit 8dd562a20f
4 changed files with 51 additions and 39 deletions

View File

@ -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.mod = glfw_modifier_to_sdl_modifier(mods);
event.key.keysym.sym = glfw_key_to_sdl_key(key); event.key.keysym.sym = glfw_key_to_sdl_key(key);
SDL_PushEvent(&event); SDL_PushEvent(&event);
if (key == GLFW_KEY_BACKSPACE && !up) {
character_event('\b');
}
} }
} }
// Pass Text To Minecraft // 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) { static void glfw_char(__attribute__((unused)) GLFWwindow *window, unsigned int codepoint) {
if (is_interactable) { if (is_interactable) {
// Signs Only Accepts ASCII Characters // Convert
size_t in_size = 4; // 1 UTF-32LE Codepoint size_t str_size = 4 /* Maximum UTF-8 character size */ + 1 /* NULL-terminator */;
size_t out_size = 4; // 4 ASCII Characters Max char str[str_size];
size_t real_out_size = out_size + 1 /* NULL-terminator */; memset(str, 0, str_size);
char *output = (char *) malloc(real_out_size); codepoint_to_utf8((unsigned char *) str, codepoint);
ALLOC_CHECK(output); char *cp437_str = to_cp437(str);
memset(output, 0, real_out_size); // Send Event·
iconv_t cd = iconv_open("ASCII//TRANSLIT", "UTF-32LE"); for (int i = 0; cp437_str[i] != '\0'; i++) {
if (cd != (iconv_t) -1) { character_event(cp437_str[i]);
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]);
} }
// Free // Free
free(output); free(cp437_str);
} }
} }

View File

@ -66,7 +66,7 @@ else()
target_link_libraries(input mods-headers reborn-patch symbols creative feature misc media-layer-core) target_link_libraries(input mods-headers reborn-patch symbols creative feature misc media-layer-core)
add_library(sign SHARED src/sign/sign.cpp) 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) add_library(touch SHARED src/touch/touch.cpp)
target_link_libraries(touch mods-headers reborn-patch symbols feature) target_link_libraries(touch mods-headers reborn-patch symbols feature)

View File

@ -1,5 +1,6 @@
#include <vector> #include <vector>
#include <SDL/SDL.h>
#include <libreborn/libreborn.h> #include <libreborn/libreborn.h>
#include <symbols/minecraft.h> #include <symbols/minecraft.h>
@ -8,6 +9,16 @@
#include <mods/input/input.h> #include <mods/input/input.h>
#include <mods/sign/sign.h> #include <mods/sign/sign.h>
// 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 // Open Sign Screen
static void LocalPlayer_openTextEdit_injection(unsigned char *local_player, unsigned char *sign) { static void LocalPlayer_openTextEdit_injection(unsigned char *local_player, unsigned char *sign) {
if (*(int32_t *) (sign + TileEntity_id_property_offset) == 4) { 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 // Store Text Input
std::vector<char> input; std::vector<char> input;
void sign_key_press(char key) { 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) { static void clear_input(__attribute__((unused)) unsigned char *minecraft) {
input.clear(); input.clear();
@ -41,28 +44,25 @@ static void TextEditScreen_updateEvents_injection(unsigned char *screen) {
// Call Original Method // Call Original Method
(*Screen_updateEvents)(screen); (*Screen_updateEvents)(screen);
if (*(char *)(screen + 4) == '\0') { if (!*(bool *)(screen + Screen_passthrough_input_property_offset)) {
unsigned char *vtable = *(unsigned char **) screen; unsigned char *vtable = *(unsigned char **) screen;
for (char key : input) { 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 // Handle Normal Key
(*(Screen_keyboardNewChar_t *) (vtable + Screen_keyboardNewChar_vtable_offset))(screen, key); (*(Screen_keyboardNewChar_t *) (vtable + Screen_keyboardNewChar_vtable_offset))(screen, key);
} }
} }
}
clear_input(NULL); clear_input(NULL);
} }
// Init // Init
void init_sign() { void init_sign() {
if (feature_has("Fix Sign Placement", server_disabled)) { 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 // Fix Signs
patch_address(LocalPlayer_openTextEdit_vtable_addr, (void *) LocalPlayer_openTextEdit_injection); patch_address(LocalPlayer_openTextEdit_vtable_addr, (void *) LocalPlayer_openTextEdit_injection);
patch_address(TextEditScreen_updateEvents_vtable_addr, (void *) TextEditScreen_updateEvents_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); input_run_on_tick(clear_input);
} }
} }

View File

@ -18,6 +18,9 @@ static renderCursor_t renderCursor = (renderCursor_t) 0x480c4;
typedef void (*sleepMs_t)(int32_t x); typedef void (*sleepMs_t)(int32_t x);
static sleepMs_t sleepMs = (sleepMs_t) 0x13cf4; 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_path = (char **) 0xe264; // /.minecraft/
static char **default_username = (char **) 0x18fd4; // StevePi static char **default_username = (char **) 0x18fd4; // StevePi
static char **minecraft_pi_version = (char **) 0x39d94; // v0.1.1 alpha 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<B
static uint32_t Screen_selectable_buttons_property_offset = 0x30; // std::vector<Button *> static uint32_t Screen_selectable_buttons_property_offset = 0x30; // std::vector<Button *>
static uint32_t Screen_width_property_offset = 0x8; // int32_t static uint32_t Screen_width_property_offset = 0x8; // int32_t
static uint32_t Screen_height_property_offset = 0xc; // int32_t static uint32_t Screen_height_property_offset = 0xc; // int32_t
static uint32_t Screen_passthrough_input_property_offset = 0x10; // bool
// Button // Button