diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 4fda7b8897..096e91433e 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -70,6 +70,7 @@ * `Screenshot Support` * `Fix Camera Functionality` * `Property Scale Animated Textures` + * `Enable Text Input` * Split Up `Remove Creative Mode Restrictions` Feature Flag * `Remove Creative Mode Restrictions` (Disabled By Default) * `Display Slot Count In Creative Mode` (Disabled By Default) @@ -79,6 +80,7 @@ * Rename Feature Flags * `Disable Buggy Held Item Caching` To `Fix Held Item Caching` * `Disable 'gui_blocks' Atlas` To `Regenerate "gui_blocks" Atlas` + * `Fix Sign Placement` To `Enable Sign Screen` * Add Milk Buckets * Included In The `Add Buckets` Feature Flag * Removed `Property Scale Animated Textures` Feature Flag diff --git a/libreborn/include/libreborn/glfw.h b/libreborn/include/libreborn/glfw.h index ff8e50a24b..4c03d21ef4 100644 --- a/libreborn/include/libreborn/glfw.h +++ b/libreborn/include/libreborn/glfw.h @@ -1,11 +1,11 @@ #pragma once // GLFW Helpers -#ifdef GLFW_VERSION_MAJOR +#ifndef GLFW_VERSION_MAJOR +#error "Missing GLFW" +#endif void init_glfw(); GLFWwindow *create_glfw_window(const char *title, int width, int height); void cleanup_glfw(GLFWwindow *window); -void get_glfw_scale(GLFWwindow *window, float *x_scale, float *y_scale); - -#endif \ No newline at end of file +void get_glfw_scale(GLFWwindow *window, float *x_scale, float *y_scale); \ No newline at end of file diff --git a/libreborn/include/libreborn/libreborn.h b/libreborn/include/libreborn/libreborn.h deleted file mode 100644 index 68d8df5580..0000000000 --- a/libreborn/include/libreborn/libreborn.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include -#include "env.h" -#include "log.h" -#include "util.h" -#include "string.h" -#include "exec.h" -#include "patch.h" -#include "glfw.h" \ No newline at end of file diff --git a/libreborn/include/libreborn/patch.h b/libreborn/include/libreborn/patch.h index 18b02477f6..7729d786fc 100644 --- a/libreborn/include/libreborn/patch.h +++ b/libreborn/include/libreborn/patch.h @@ -3,7 +3,9 @@ #include "log.h" // Patching Functions -#ifdef REBORN_HAS_PATCH_CODE +#ifndef REBORN_HAS_PATCH_CODE +#error "Missing Patching Functions" +#endif // Init void reborn_init_patch(); @@ -50,5 +52,3 @@ void patch_vtable(const T *start, typename T::ptr_type target) { } patch_address((void *) start->get_vtable_addr(), (void *) target); } - -#endif diff --git a/libreborn/src/util/flags/available-feature-flags b/libreborn/src/util/flags/available-feature-flags index 923065f479..3b41d80b11 100644 --- a/libreborn/src/util/flags/available-feature-flags +++ b/libreborn/src/util/flags/available-feature-flags @@ -26,6 +26,7 @@ CATEGORY User Interface TRUE Implement Create World Dialog TRUE Display Date In Select World Screen TRUE Add Welcome Screen + TRUE Enable Sign Screen CATEGORY HUD TRUE Classic HUD TRUE Translucent Toolbar @@ -84,6 +85,7 @@ CATEGORY Input FALSE Disable Raw Mouse Motion (Not Recommended) FALSE Disable Speed Bridging FALSE Disable Creative Mode Mining Delay + TRUE Enable Text Input CATEGORY Multiplayer CATEGORY Chat TRUE Implement Chat @@ -96,7 +98,6 @@ CATEGORY Gameplay TRUE Implement Death Messages TRUE Implement Game-Mode Switching FALSE Force Mob Spawning - TRUE Fix Sign Placement TRUE Add Buckets TRUE Load Custom Skins TRUE Add Cake diff --git a/mods/CMakeLists.txt b/mods/CMakeLists.txt index f1e4e95302..07689ff9ab 100644 --- a/mods/CMakeLists.txt +++ b/mods/CMakeLists.txt @@ -4,12 +4,12 @@ project(mods) add_library(mods SHARED # compat src/compat/compat.cpp - src/compat/egl.cpp - src/compat/x11.cpp - src/compat/bcm_host.cpp + src/compat/readdir.cpp src/compat/sdl.cpp - # readdir - src/readdir/readdir.cpp + src/compat/stubs/egl.cpp + src/compat/stubs/x11.cpp + src/compat/stubs/bcm_host.cpp + src/compat/stubs/sdl.cpp # feature src/feature/feature.cpp # version @@ -63,8 +63,6 @@ add_library(mods SHARED src/input/misc.cpp src/input/drop.cpp src/input/keys.cpp - # sign - src/sign/sign.cpp # atlas src/atlas/atlas.cpp # title-screen diff --git a/mods/include/mods/init/init.h b/mods/include/mods/init/init.h index 4e8dad6127..2fbb415f92 100644 --- a/mods/include/mods/init/init.h +++ b/mods/include/mods/init/init.h @@ -8,7 +8,6 @@ void init_multiplayer(); void init_benchmark(); void init_sound(); void init_input(); -void init_sign(); void init_camera(); void init_atlas(); void init_title_screen(); diff --git a/mods/include/mods/sign/sign.h b/mods/include/mods/sign/sign.h deleted file mode 100644 index 46e5dd97d4..0000000000 --- a/mods/include/mods/sign/sign.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -extern "C" { -void sign_key_press(char key); -} \ No newline at end of file diff --git a/mods/src/compat/README.md b/mods/src/compat/README.md index 3fe8e4b335..3a1671c05f 100644 --- a/mods/src/compat/README.md +++ b/mods/src/compat/README.md @@ -1,2 +1,2 @@ # `compat` Mod -This utility mod sends keyboard input to other mods. It also patches out all EGL and X11 calls. +This utility mod ensures compatibility with the host system. This includes fixing events, handling signals, and patching out bad function calls. \ No newline at end of file diff --git a/mods/src/compat/compat-internal.h b/mods/src/compat/compat-internal.h index 488851240c..402badfd03 100644 --- a/mods/src/compat/compat-internal.h +++ b/mods/src/compat/compat-internal.h @@ -1,6 +1,10 @@ #pragma once +// Stubs __attribute__((visibility("internal"))) void _patch_egl_calls(); __attribute__((visibility("internal"))) void _patch_x11_calls(); __attribute__((visibility("internal"))) void _patch_bcm_host_calls(); __attribute__((visibility("internal"))) void _patch_sdl_calls(); + +// Functionality +__attribute__((visibility("internal"))) void _init_compat_sdl(); diff --git a/mods/src/compat/compat.cpp b/mods/src/compat/compat.cpp index 4ae8ed0cad..175e52ac48 100644 --- a/mods/src/compat/compat.cpp +++ b/mods/src/compat/compat.cpp @@ -1,92 +1,19 @@ #include #include -#include #include #include + #include "compat-internal.h" -#include -#include -#include - -#include -#include - -#include -#include - -// Custom Title -HOOK(media_SDL_WM_SetCaption, void, (__attribute__((unused)) const char *title, const char *icon)) { - real_media_SDL_WM_SetCaption()(MCPI_APP_TITLE, icon); -} - -// Mouse Cursor Is Always Invisible In Vanilla MCPI -// Because In Vanilla MCPI, The GPU Overlay Covered The Normal Mouse Cursor -HOOK(media_SDL_ShowCursor, int, (int toggle)) { - return real_media_SDL_ShowCursor()(toggle == SDL_QUERY ? SDL_QUERY : SDL_DISABLE); -} - -// Intercept SDL Events -HOOK(media_SDL_PollEvent, int, (SDL_Event *event)) { - // In Server Mode, Exit Requests Are Handled In src/server/server.cpp - // Check If Exit Is Requested - if (!reborn_is_server() && compat_check_exit_requested()) { - // Send SDL_QUIT - SDL_Event new_event; - new_event.type = SDL_QUIT; - media_SDL_PushEvent(&new_event); - } - - // Poll Events - int ret = real_media_SDL_PollEvent()(event); - - // Handle Events - if (ret == 1 && event != nullptr) { - bool handled = false; - switch (event->type) { - case SDL_KEYDOWN: - case SDL_KEYUP: { - // Track Control Key - bool is_ctrl = (event->key.keysym.mod & KMOD_CTRL) != 0; - if (event->type == SDL_KEYUP) { - is_ctrl = false; - } - input_set_is_ctrl(is_ctrl); - break; - } - case SDL_MOUSEBUTTONDOWN: - case SDL_MOUSEBUTTONUP: { - // Track Right-Click State - if (event->button.button == SDL_BUTTON_RIGHT) { - input_set_is_right_click(event->button.state != SDL_RELEASED); - } - break; - } - case SDL_USEREVENT: { - // SDL_UserEvent Is Never Used In MCPI, So It Is Repurposed For Character Events - if (event->user.code == USER_EVENT_CHARACTER) { - sign_key_press((char) event->user.data1); - handled = true; - } - break; - } - } - if (handled) { - // Event Was Handled - return media_SDL_PollEvent(event); - } - } - - return ret; -} - // Exit Handler static void exit_handler(__attribute__((unused)) int data) { // Request Exit compat_request_exit(); } void init_compat() { + // SDL + _init_compat_sdl(); // Install Signal Handlers struct sigaction act_sigint = {}; act_sigint.sa_flags = SA_RESTART; diff --git a/mods/src/readdir/readdir.cpp b/mods/src/compat/readdir.cpp similarity index 100% rename from mods/src/readdir/readdir.cpp rename to mods/src/compat/readdir.cpp diff --git a/mods/src/compat/sdl.cpp b/mods/src/compat/sdl.cpp index e0c8857524..1ecc8848bf 100644 --- a/mods/src/compat/sdl.cpp +++ b/mods/src/compat/sdl.cpp @@ -1,43 +1,85 @@ #include - #include -#include + +#include +#include + +#include + +#include +#include +#include + #include "compat-internal.h" -// SDL Stub -static void *SDL_SetVideoMode_injection(__attribute__((unused)) int width, __attribute__((unused)) int height, __attribute__((unused)) int bpp, __attribute__((unused)) uint32_t flags) { - // Return Value Is Only Used For A NULL-Check - return (void *) 1; +// Custom Title +HOOK(media_SDL_WM_SetCaption, void, (__attribute__((unused)) const char *title, const char *icon)) { + real_media_SDL_WM_SetCaption()(MCPI_APP_TITLE, icon); } -// Window Information -static void x11_nop() { - // NOP -} -static int SDL_GetWMInfo_injection(SDL_SysWMinfo *info) { - // Return Fake Lock Functions Since XLib Isn't Directly Used - SDL_SysWMinfo ret; - ret.info.x11.lock_func = x11_nop; - ret.info.x11.unlock_func = x11_nop; - ret.info.x11.display = nullptr; - ret.info.x11.window = 0; - ret.info.x11.wmwindow = ret.info.x11.window; - *info = ret; - return 1; +// Mouse Cursor Is Always Invisible In Vanilla MCPI +// Because In Vanilla MCPI, The GPU Overlay Covered The Normal Mouse Cursor +HOOK(media_SDL_ShowCursor, int, (int toggle)) { + return real_media_SDL_ShowCursor()(toggle == SDL_QUERY ? SDL_QUERY : SDL_DISABLE); } -// Quit -static void SDL_Quit_injection() { - // Cleanup Media Layer - media_cleanup(); - // Exit - INFO("Stopped"); +// Intercept SDL Events +static bool enable_text_events; +HOOK(media_SDL_PollEvent, int, (SDL_Event *event)) { + // In Server Mode, Exit Requests Are Handled In src/server/server.cpp + // Check If Exit Is Requested + if (!reborn_is_server() && compat_check_exit_requested()) { + // Send SDL_QUIT + SDL_Event new_event; + new_event.type = SDL_QUIT; + media_SDL_PushEvent(&new_event); + } + + // Poll Events + int ret = real_media_SDL_PollEvent()(event); + + // Handle Events + if (ret == 1 && event != nullptr) { + bool handled = false; + switch (event->type) { + case SDL_KEYDOWN: + case SDL_KEYUP: { + // Track Control Key + bool is_ctrl = (event->key.keysym.mod & KMOD_CTRL) != 0; + if (event->type == SDL_KEYUP) { + is_ctrl = false; + } + input_set_is_ctrl(is_ctrl); + break; + } + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: { + // Track Right-Click State + if (event->button.button == SDL_BUTTON_RIGHT) { + input_set_is_right_click(event->button.state != SDL_RELEASED); + } + break; + } + case SDL_USEREVENT: { + // SDL_UserEvent Is Never Used In MCPI, So It Is Repurposed For Character Events + if (event->user.code == USER_EVENT_CHARACTER) { + if (enable_text_events) { + Keyboard::_inputText.push_back(char(event->user.data1)); + } + handled = true; + } + break; + } + } + if (handled) { + // Event Was Handled + return media_SDL_PollEvent(event); + } + } + return ret; } -// Patch SDL Calls -void _patch_sdl_calls() { - // Disable SDL Calls - overwrite_call((void *) 0xe020, (void *) SDL_SetVideoMode_injection); - overwrite_call((void *) 0x13284, (void *) SDL_GetWMInfo_injection); - overwrite_call((void *) 0x12410, (void *) SDL_Quit_injection); -} +// Init +void _init_compat_sdl() { + enable_text_events = feature_has("Enable Text Input", server_disabled); +} \ No newline at end of file diff --git a/mods/src/compat/bcm_host.cpp b/mods/src/compat/stubs/bcm_host.cpp similarity index 96% rename from mods/src/compat/bcm_host.cpp rename to mods/src/compat/stubs/bcm_host.cpp index 0e3d03d87c..b5d9c4cd7c 100644 --- a/mods/src/compat/bcm_host.cpp +++ b/mods/src/compat/stubs/bcm_host.cpp @@ -1,5 +1,5 @@ #include -#include "compat-internal.h" +#include "../compat-internal.h" // Do Nothing Function static void do_nothing() { diff --git a/mods/src/compat/egl.cpp b/mods/src/compat/stubs/egl.cpp similarity index 98% rename from mods/src/compat/egl.cpp rename to mods/src/compat/stubs/egl.cpp index 6c2a2d62d6..a18fea5883 100644 --- a/mods/src/compat/egl.cpp +++ b/mods/src/compat/stubs/egl.cpp @@ -2,7 +2,7 @@ #include #include -#include "compat-internal.h" +#include "../compat-internal.h" // 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) { diff --git a/mods/src/compat/stubs/sdl.cpp b/mods/src/compat/stubs/sdl.cpp new file mode 100644 index 0000000000..b31a49eff4 --- /dev/null +++ b/mods/src/compat/stubs/sdl.cpp @@ -0,0 +1,43 @@ +#include + +#include +#include +#include "../compat-internal.h" + +// SDL Stub +static void *SDL_SetVideoMode_injection(__attribute__((unused)) int width, __attribute__((unused)) int height, __attribute__((unused)) int bpp, __attribute__((unused)) uint32_t flags) { + // Return Value Is Only Used For A NULL-Check + return (void *) 1; +} + +// Window Information +static void x11_nop() { + // NOP +} +static int SDL_GetWMInfo_injection(SDL_SysWMinfo *info) { + // Return Fake Lock Functions Since XLib Isn't Directly Used + SDL_SysWMinfo ret; + ret.info.x11.lock_func = x11_nop; + ret.info.x11.unlock_func = x11_nop; + ret.info.x11.display = nullptr; + ret.info.x11.window = 0; + ret.info.x11.wmwindow = ret.info.x11.window; + *info = ret; + return 1; +} + +// Quit +static void SDL_Quit_injection() { + // Cleanup Media Layer + media_cleanup(); + // Exit + INFO("Stopped"); +} + +// Patch SDL Calls +void _patch_sdl_calls() { + // Disable SDL Calls + overwrite_call((void *) 0xe020, (void *) SDL_SetVideoMode_injection); + overwrite_call((void *) 0x13284, (void *) SDL_GetWMInfo_injection); + overwrite_call((void *) 0x12410, (void *) SDL_Quit_injection); +} diff --git a/mods/src/compat/x11.cpp b/mods/src/compat/stubs/x11.cpp similarity index 97% rename from mods/src/compat/x11.cpp rename to mods/src/compat/stubs/x11.cpp index d44d97065c..360f60fdc7 100644 --- a/mods/src/compat/x11.cpp +++ b/mods/src/compat/stubs/x11.cpp @@ -2,7 +2,7 @@ #include #include -#include "compat-internal.h" +#include "../compat-internal.h" // Functions That Have Their Return Values Used static int XTranslateCoordinates_injection(__attribute__((unused)) void *display, __attribute__((unused)) XID src_w, __attribute__((unused)) XID dest_w, int src_x, int src_y, int *dest_x_return, int *dest_y_return, __attribute__((unused)) XID *child_return) { diff --git a/mods/src/init/init.cpp b/mods/src/init/init.cpp index 38d49dabf7..e903c32be3 100644 --- a/mods/src/init/init.cpp +++ b/mods/src/init/init.cpp @@ -18,7 +18,6 @@ __attribute__((constructor)) static void init() { init_shading(); } init_input(); - init_sign(); init_camera(); if (!reborn_is_headless()) { init_atlas(); diff --git a/mods/src/misc/README.md b/mods/src/misc/README.md index b8e570947f..54f4a6a523 100644 --- a/mods/src/misc/README.md +++ b/mods/src/misc/README.md @@ -6,4 +6,4 @@ This mod has several miscellaneous mods that are too small to be their own mod, * Loading the bundled language file. * Printing chat messages to the log. * Implementing crafting remainders. -* Correct the profile directory. \ No newline at end of file +* Correcting the profile directory. \ No newline at end of file diff --git a/mods/src/misc/ui.cpp b/mods/src/misc/ui.cpp index 3ca0befc12..928be4b61e 100644 --- a/mods/src/misc/ui.cpp +++ b/mods/src/misc/ui.cpp @@ -236,6 +236,16 @@ static void Minecraft_handleMouseDown_injection(Minecraft_handleMouseDown_t orig } } +// Open Sign Screen +static void LocalPlayer_openTextEdit_injection(__attribute__((unused)) LocalPlayer_openTextEdit_t original, LocalPlayer *local_player, TileEntity *sign) { + if (sign->type == 4) { + Minecraft *minecraft = local_player->minecraft; + TextEditScreen *screen = TextEditScreen::allocate(); + screen = screen->constructor((SignTileEntity *) sign); + minecraft->setScreen((Screen *) screen); + } +} + // Init void _init_misc_ui() { // Food Overlay @@ -327,4 +337,10 @@ void _init_misc_ui() { overwrite_calls(Minecraft_grabMouse, Minecraft_grabMouse_injection); overwrite_calls(Minecraft_handleMouseDown, Minecraft_handleMouseDown_injection); } + + // Signs + if (feature_has("Enable Sign Screen", server_disabled)) { + // Fix Signs + overwrite_calls(LocalPlayer_openTextEdit, LocalPlayer_openTextEdit_injection); + } } diff --git a/mods/src/readdir/README.md b/mods/src/readdir/README.md deleted file mode 100644 index ee92b12279..0000000000 --- a/mods/src/readdir/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# `readdir` Mod -This mod fixes a small bug where the contents of directories cannot be read on a 64-bit filesystem. This notably broke the world selection screen. diff --git a/mods/src/sign/README.md b/mods/src/sign/README.md deleted file mode 100644 index fbdf13b01e..0000000000 --- a/mods/src/sign/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# `sign` Mod -This mod fixes sign placement. diff --git a/mods/src/sign/sign.cpp b/mods/src/sign/sign.cpp deleted file mode 100644 index 6506e6a5c4..0000000000 --- a/mods/src/sign/sign.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include - -#include - -#include - -#include -#include -#include - -// Open Sign Screen -static void LocalPlayer_openTextEdit_injection(__attribute__((unused)) LocalPlayer_openTextEdit_t original, LocalPlayer *local_player, TileEntity *sign) { - if (sign->type == 4) { - Minecraft *minecraft = local_player->minecraft; - TextEditScreen *screen = TextEditScreen::allocate(); - screen = screen->constructor((SignTileEntity *) sign); - minecraft->setScreen((Screen *) screen); - } -} - -// Store Text Input -void sign_key_press(const char key) { - Keyboard::_inputText.push_back(key); -} - -// Init -void init_sign() { - if (feature_has("Fix Sign Placement", server_disabled)) { - // Fix Signs - overwrite_calls(LocalPlayer_openTextEdit, LocalPlayer_openTextEdit_injection); - } -}