Fix Mouse Cursor Bugs
All checks were successful
minecraft-pi-reborn/pipeline/head This commit looks good
All checks were successful
minecraft-pi-reborn/pipeline/head This commit looks good
This commit is contained in:
parent
0f6c3c2e43
commit
747d2032e6
@ -1,5 +1,8 @@
|
||||
# Changelog
|
||||
|
||||
**2.0.2**
|
||||
* Fix Mouse Cursor Bugs
|
||||
|
||||
**2.0.1**
|
||||
* Fix Blank Screen On Twister OS
|
||||
|
||||
|
@ -12,6 +12,9 @@ typedef uint32_t bool;
|
||||
|
||||
// Globals
|
||||
|
||||
typedef void (*renderCursor_t)(float x, float y, unsigned char *minecraft);
|
||||
static renderCursor_t renderCursor = (renderCursor_t) 0x480c4;
|
||||
|
||||
static char **default_path = (char **) 0xe264; // /.minecraft/
|
||||
static char **default_username = (char **) 0x18fd4; // StevePi
|
||||
|
||||
@ -120,6 +123,20 @@ static uint32_t Minecraft_command_server_property_offset = 0xcc0; // CommandServ
|
||||
static uint32_t Minecraft_screen_property_offset = 0xc10; // Screen *
|
||||
static uint32_t Minecraft_gui_property_offset = 0x198; // Gui
|
||||
|
||||
// GameRenderer
|
||||
|
||||
typedef void (*GameRenderer_render_t)(unsigned char *game_renderer, float param_1);
|
||||
static GameRenderer_render_t GameRenderer_render = (GameRenderer_render_t) 0x4a338;
|
||||
|
||||
static uint32_t GameRenderer_minecraft_property_offset = 0x4; // Minecraft *
|
||||
|
||||
// Mouse
|
||||
|
||||
typedef int (*Mouse_get_t)();
|
||||
|
||||
static Mouse_get_t Mouse_getX = (Mouse_get_t) 0x1385c;
|
||||
static Mouse_get_t Mouse_getY = (Mouse_get_t) 0x1386c;
|
||||
|
||||
// CommandServer
|
||||
|
||||
static uint32_t CommandServer_minecraft_property_offset = 0x18; // Minecraft *
|
||||
|
@ -280,39 +280,82 @@ void media_cleanup() {
|
||||
#endif // #ifndef MCPI_SERVER_MODE
|
||||
}
|
||||
|
||||
#ifdef MCPI_SERVER_MODE
|
||||
static SDL_GrabMode fake_grab_mode = SDL_GRAB_OFF;
|
||||
#endif // #ifdef MCPI_SERVER_MODE
|
||||
// Store Cursor State
|
||||
static int cursor_grabbed = 0;
|
||||
static int cursor_visible = 1;
|
||||
|
||||
// Update GLFW Cursor State (Client Only)
|
||||
#ifndef MCPI_SERVER_MODE
|
||||
static void update_glfw_cursor() {
|
||||
// Store Old Mode
|
||||
int old_mode = glfwGetInputMode(glfw_window, GLFW_CURSOR);
|
||||
|
||||
// Handle Cursor Visibility
|
||||
int new_mode;
|
||||
if (!cursor_visible) {
|
||||
if (cursor_grabbed) {
|
||||
new_mode = GLFW_CURSOR_DISABLED;
|
||||
} else {
|
||||
new_mode = GLFW_CURSOR_HIDDEN;
|
||||
}
|
||||
} else {
|
||||
new_mode = GLFW_CURSOR_NORMAL;
|
||||
}
|
||||
if (new_mode != old_mode) {
|
||||
// Set New Mode
|
||||
glfwSetInputMode(glfw_window, GLFW_CURSOR, new_mode);
|
||||
|
||||
// Handle Cursor Lock/Unlock
|
||||
if ((new_mode == GLFW_CURSOR_DISABLED && old_mode != GLFW_CURSOR_DISABLED) || (new_mode != GLFW_CURSOR_DISABLED && old_mode == GLFW_CURSOR_DISABLED)) {
|
||||
// Use Raw Mouse Motion (GLFW 3.3+ Only)
|
||||
#ifdef GLFW_RAW_MOUSE_MOTION
|
||||
glfwSetInputMode(glfw_window, GLFW_RAW_MOUSE_MOTION, new_mode == GLFW_CURSOR_DISABLED ? GLFW_TRUE : GLFW_FALSE);
|
||||
#endif
|
||||
// Reset Last Mouse Position
|
||||
ignore_relative_mouse = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Fix SDL Cursor Visibility/Grabbing
|
||||
SDL_GrabMode SDL_WM_GrabInput(SDL_GrabMode mode) {
|
||||
#ifdef MCPI_SERVER_MODE
|
||||
// Don't Grab Input In Server Mode
|
||||
if (mode != SDL_GRAB_QUERY) {
|
||||
fake_grab_mode = mode;
|
||||
if (mode == SDL_GRAB_QUERY) {
|
||||
// Query
|
||||
return cursor_grabbed ? SDL_GRAB_ON : SDL_GRAB_OFF;
|
||||
} else if (mode == SDL_GRAB_ON) {
|
||||
// Store State
|
||||
cursor_grabbed = 1;
|
||||
} else if (mode == SDL_GRAB_OFF) {
|
||||
// Store State
|
||||
cursor_grabbed = 0;
|
||||
}
|
||||
return fake_grab_mode;
|
||||
#else // #ifdef MCPI_SERVER_MODE
|
||||
if (mode != SDL_GRAB_QUERY && mode != SDL_WM_GrabInput(SDL_GRAB_QUERY)) {
|
||||
glfwSetInputMode(glfw_window, GLFW_CURSOR, mode == SDL_GRAB_OFF ? GLFW_CURSOR_NORMAL : GLFW_CURSOR_DISABLED);
|
||||
#if GLFW_VERSION_MAJOR > 3 || (GLFW_VERSION_MAJOR == 3 && GLFW_VERSION_MINOR >= 3)
|
||||
glfwSetInputMode(glfw_window, GLFW_RAW_MOUSE_MOTION, mode == SDL_GRAB_OFF ? GLFW_FALSE : GLFW_TRUE);
|
||||
#endif // #if GLFW_VERSION_MAJOR > 3 || (GLFW_VERSION_MAJOR == 3 && GLFW_VERSION_MINOR >= 3)
|
||||
|
||||
// Reset Last Mouse Position
|
||||
ignore_relative_mouse = 1;
|
||||
}
|
||||
return mode == SDL_GRAB_QUERY ? (glfwGetInputMode(glfw_window, GLFW_CURSOR) == GLFW_CURSOR_NORMAL ? SDL_GRAB_OFF : SDL_GRAB_ON) : mode;
|
||||
#endif // #ifdef MCPI_SERVER_MODE
|
||||
// Update Cursor GLFW State (Client Only)
|
||||
#ifndef MCPI_SERVER_MODE
|
||||
update_glfw_cursor();
|
||||
#endif
|
||||
// Return
|
||||
return mode;
|
||||
}
|
||||
|
||||
// Stub SDL Cursor Visibility
|
||||
int SDL_ShowCursor(int toggle) {
|
||||
#ifdef MCPI_SERVER_MODE
|
||||
return toggle == SDL_QUERY ? (fake_grab_mode == SDL_GRAB_OFF ? SDL_ENABLE : SDL_DISABLE) : toggle;
|
||||
#else // #ifdef MCPI_SERVER_MODE
|
||||
return toggle == SDL_QUERY ? (glfwGetInputMode(glfw_window, GLFW_CURSOR) == GLFW_CURSOR_NORMAL ? SDL_ENABLE : SDL_DISABLE) : toggle;
|
||||
#endif // #ifdef MCPI_SERVER_MODE
|
||||
if (toggle == SDL_QUERY) {
|
||||
// Query
|
||||
return cursor_visible ? SDL_ENABLE : SDL_DISABLE;
|
||||
} else if (toggle == SDL_ENABLE) {
|
||||
// Store State
|
||||
cursor_visible = 1;
|
||||
} else if (toggle == SDL_DISABLE) {
|
||||
// Store State
|
||||
cursor_visible = 0;
|
||||
}
|
||||
// Update Cursor GLFW State (Client Only)
|
||||
#ifndef MCPI_SERVER_MODE
|
||||
update_glfw_cursor();
|
||||
#endif
|
||||
// Return
|
||||
return toggle;
|
||||
}
|
||||
|
||||
// Get Framebuffer Size
|
||||
|
@ -35,6 +35,9 @@ target_link_libraries(misc reborn feature util)
|
||||
add_library(options SHARED src/options/options.c)
|
||||
target_link_libraries(options reborn feature)
|
||||
|
||||
add_library(touch SHARED src/touch/touch.c)
|
||||
target_link_libraries(touch reborn feature)
|
||||
|
||||
add_library(override SHARED src/override/override.c)
|
||||
target_link_libraries(override reborn dl home)
|
||||
|
||||
@ -51,13 +54,13 @@ add_library(test SHARED src/test/test.c)
|
||||
target_link_libraries(test reborn home)
|
||||
|
||||
add_library(init SHARED src/init/init.c)
|
||||
target_link_libraries(init compat game_mode camera input misc options textures chat home test)
|
||||
target_link_libraries(init compat game_mode camera input misc options touch textures chat home test)
|
||||
if(MCPI_SERVER_MODE)
|
||||
target_link_libraries(init server)
|
||||
endif()
|
||||
|
||||
## Install Mods
|
||||
install(TARGETS init compat readdir feature override game_mode camera input misc options textures chat home test DESTINATION "${MCPI_INSTALL_DIR}/mods")
|
||||
install(TARGETS init compat readdir feature override game_mode camera input misc options touch textures chat home test DESTINATION "${MCPI_INSTALL_DIR}/mods")
|
||||
if(MCPI_SERVER_MODE)
|
||||
install(TARGETS server DESTINATION "${MCPI_INSTALL_DIR}/mods")
|
||||
endif()
|
||||
|
@ -12,6 +12,13 @@
|
||||
#include "../init/init.h"
|
||||
#include "compat.h"
|
||||
|
||||
// Mouse Cursor Is Always Invisible In Vanilla MCPI
|
||||
// Because In Vanilla MCPI, The GPU Overlay Covered The Normal Mouse Cursor
|
||||
HOOK(SDL_ShowCursor, int, (int toggle)) {
|
||||
ensure_SDL_ShowCursor();
|
||||
return (*real_SDL_ShowCursor)(toggle == SDL_QUERY ? SDL_QUERY : SDL_DISABLE);
|
||||
}
|
||||
|
||||
// Intercept SDL Events
|
||||
HOOK(SDL_PollEvent, int, (SDL_Event *event)) {
|
||||
// In Server Mode, Exit Requests Are Handled In src/server/server.cpp
|
||||
|
@ -4,17 +4,17 @@
|
||||
#include <libreborn/media-layer/core.h>
|
||||
|
||||
// Functions That Have Their Return Values Used
|
||||
static EGLSurface eglCreateWindowSurface_overwrite(__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLConfig config, __attribute__((unused)) NativeWindowType native_window, __attribute__((unused)) EGLint const *attrib_list) {
|
||||
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;
|
||||
}
|
||||
static EGLDisplay eglGetDisplay_overwrite(__attribute__((unused)) NativeDisplayType native_display) {
|
||||
static EGLDisplay eglGetDisplay_injection(__attribute__((unused)) NativeDisplayType native_display) {
|
||||
return 0;
|
||||
}
|
||||
static EGLContext eglCreateContext_overwrite(__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLConfig config, __attribute__((unused)) EGLContext share_context, __attribute__((unused)) EGLint const *attrib_list) {
|
||||
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;
|
||||
}
|
||||
// Call media_swap_buffers()
|
||||
static EGLBoolean eglSwapBuffers_overwrite(__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLSurface surface) {
|
||||
static EGLBoolean eglSwapBuffers_injection(__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLSurface surface) {
|
||||
media_swap_buffers();
|
||||
return EGL_TRUE;
|
||||
}
|
||||
@ -25,15 +25,15 @@ __attribute__((constructor)) static void patch_egl_calls() {
|
||||
unsigned char nop_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop"
|
||||
patch((void *) 0x1250c, nop_patch); // eglTerminate
|
||||
patch((void *) 0x12580, nop_patch); // eglBindAPI
|
||||
overwrite_call((void *) 0x12638, (void *) eglCreateWindowSurface_overwrite); // eglCreateWindowSurface
|
||||
overwrite_call((void *) 0x12638, (void *) eglCreateWindowSurface_injection); // eglCreateWindowSurface
|
||||
patch((void *) 0x12578, nop_patch); // eglChooseConfig
|
||||
patch((void *) 0x1255c, nop_patch); // eglInitialize
|
||||
patch((void *) 0x124f0, nop_patch); // eglMakeCurrent #1
|
||||
patch((void *) 0x12654, nop_patch); // eglMakeCurrent #2
|
||||
overwrite_call((void *) 0x124dc, (void *) eglSwapBuffers_overwrite); // eglSwapBuffers #1
|
||||
overwrite_call((void *) 0x14b6c, (void *) eglSwapBuffers_overwrite); // eglSwapBuffers #2
|
||||
overwrite_call((void *) 0x1254c, (void *) eglGetDisplay_overwrite); // eglGetDisplay
|
||||
overwrite_call((void *) 0x124dc, (void *) eglSwapBuffers_injection); // eglSwapBuffers #1
|
||||
overwrite_call((void *) 0x14b6c, (void *) eglSwapBuffers_injection); // eglSwapBuffers #2
|
||||
overwrite_call((void *) 0x1254c, (void *) eglGetDisplay_injection); // eglGetDisplay
|
||||
patch((void *) 0x124fc, nop_patch); // eglDestroySurface #1
|
||||
patch((void *) 0x12504, nop_patch); // eglDestroySurface #2
|
||||
overwrite_call((void *) 0x12594, (void *) eglCreateContext_overwrite); // eglCreateContext
|
||||
overwrite_call((void *) 0x12594, (void *) eglCreateContext_injection); // eglCreateContext
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ __attribute__((constructor)) static void init() {
|
||||
init_misc();
|
||||
init_camera();
|
||||
init_options();
|
||||
init_touch();
|
||||
init_textures();
|
||||
init_chat();
|
||||
init_home();
|
||||
|
@ -14,6 +14,7 @@ void init_input();
|
||||
void init_misc();
|
||||
void init_camera();
|
||||
void init_options();
|
||||
void init_touch();
|
||||
void init_textures();
|
||||
void init_chat();
|
||||
void init_home();
|
||||
|
@ -3,7 +3,6 @@ This mod allows various options to be configured, including:
|
||||
- Mob Spawning
|
||||
- The Render Distance
|
||||
- The Username
|
||||
- Touch GUI
|
||||
- Peaceful Mode
|
||||
- 3D Anaglyph
|
||||
- Autojump
|
||||
|
@ -68,21 +68,8 @@ static void Minecraft_init_injection(unsigned char *this) {
|
||||
*(int32_t *) (options + Options_render_distance_property_offset) = render_distance;
|
||||
}
|
||||
|
||||
// Enable Touch GUI
|
||||
static int32_t Minecraft_isTouchscreen_injection(__attribute__((unused)) unsigned char *minecraft) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Init
|
||||
void init_options() {
|
||||
int touch_gui = feature_has("Touch GUI");
|
||||
if (touch_gui) {
|
||||
// Main UI
|
||||
overwrite((void *) Minecraft_isTouchscreen, Minecraft_isTouchscreen_injection);
|
||||
// Force Correct Toolbar Size
|
||||
unsigned char toolbar_patch[4] = {0x01, 0x00, 0x50, 0xe3}; // "cmp r0, #0x1"
|
||||
patch((void *) 0x257b0, toolbar_patch);
|
||||
}
|
||||
|
||||
mob_spawning = feature_has("Mob Spawning");
|
||||
// Set Mob Spawning
|
||||
overwrite((void *) LevelData_getSpawnMobs, LevelData_getSpawnMobs_injection);
|
||||
@ -125,15 +112,10 @@ void init_options() {
|
||||
patch((void *) 0xa6628, display_nametags_patch);
|
||||
}
|
||||
|
||||
// Show Block Outlines
|
||||
int block_outlines = feature_has("Show Block Outlines");
|
||||
unsigned char outline_patch[4] = {block_outlines ? !touch_gui : touch_gui, 0x00, 0x50, 0xe3}; // "cmp r0, #0x1" or "cmp r0, #0x0"
|
||||
patch((void *) 0x4a210, outline_patch);
|
||||
|
||||
smooth_lighting = feature_has("Smooth Lighting");
|
||||
if (smooth_lighting) {
|
||||
// Enable Smooth Lighting
|
||||
unsigned char smooth_lighting_patch[4] = {0x01, 0x00, 0x53, 0xe3}; // "cmp r3, #0x1"
|
||||
patch((void *) 0x59ea4, smooth_lighting_patch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
2
mods/src/touch/README.md
Normal file
2
mods/src/touch/README.md
Normal file
@ -0,0 +1,2 @@
|
||||
# ``touch`` Mod
|
||||
This mod allows the hidden touch GUI to be activated.
|
54
mods/src/touch/touch.c
Normal file
54
mods/src/touch/touch.c
Normal file
@ -0,0 +1,54 @@
|
||||
#include <libreborn/libreborn.h>
|
||||
|
||||
#include "../feature/feature.h"
|
||||
#include "../init/init.h"
|
||||
|
||||
#include <libreborn/minecraft.h>
|
||||
|
||||
// Enable Touch GUI
|
||||
static int32_t Minecraft_isTouchscreen_injection(__attribute__((unused)) unsigned char *minecraft) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Custom Cursor Rendering
|
||||
// The Default Behavior For Touch GUI Is To Only Render The Cursor When The Mouse Is Clicking, This Fixes That
|
||||
static void GameRenderer_render_injection(unsigned char *game_renderer, float param_1) {
|
||||
// Call Real Method
|
||||
(*GameRenderer_render)(game_renderer, param_1);
|
||||
|
||||
// Render Cursor
|
||||
unsigned char *minecraft = *(unsigned char **) (game_renderer + GameRenderer_minecraft_property_offset);
|
||||
unsigned char *current_screen = *(unsigned char **) (minecraft + Minecraft_screen_property_offset);
|
||||
// Check If Cursor Should Render
|
||||
if (current_screen != NULL) {
|
||||
// Get X And Y
|
||||
float x = (*Mouse_getX)() * (*InvGuiScale);
|
||||
float y = (*Mouse_getY)() * (*InvGuiScale);
|
||||
// Render
|
||||
(*renderCursor)(x, y, minecraft);
|
||||
}
|
||||
}
|
||||
|
||||
// Init
|
||||
void init_touch() {
|
||||
int touch_gui = feature_has("Touch GUI");
|
||||
if (touch_gui) {
|
||||
// Main UI
|
||||
overwrite((void *) Minecraft_isTouchscreen, Minecraft_isTouchscreen_injection);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// Force Correct Toolbar Size
|
||||
unsigned char toolbar_patch[4] = {0x01, 0x00, 0x50, 0xe3}; // "cmp r0, #0x1"
|
||||
patch((void *) 0x257b0, toolbar_patch);
|
||||
|
||||
// Show Block Outlines
|
||||
int block_outlines = feature_has("Show Block Outlines");
|
||||
unsigned char outline_patch[4] = {block_outlines ? !touch_gui : touch_gui, 0x00, 0x50, 0xe3}; // "cmp r0, #0x1" or "cmp r0, #0x0"
|
||||
patch((void *) 0x4a210, outline_patch);
|
||||
}
|
Loading…
Reference in New Issue
Block a user