From 29d3599d767a08b2add6d005abe3359b8abff3bf Mon Sep 17 00:00:00 2001 From: GameParrot <85067619+GameParrot@users.noreply.github.com> Date: Fri, 27 Dec 2024 15:32:01 -0500 Subject: [PATCH 1/4] gamewindow api --- src/core_patches.cpp | 56 +++++++++++++++---- src/core_patches.h | 13 +++-- src/jni/main_activity.cpp | 30 +++++++---- src/jni/main_activity.h | 21 +++----- src/main.cpp | 2 + src/window_callbacks.cpp | 110 ++++++++++++++++++++++++++++++++------ src/window_callbacks.h | 38 ++++++++++++- 7 files changed, 217 insertions(+), 53 deletions(-) diff --git a/src/core_patches.cpp b/src/core_patches.cpp index 8eb66f98..213b17d2 100644 --- a/src/core_patches.cpp +++ b/src/core_patches.cpp @@ -4,9 +4,7 @@ #include #include -std::shared_ptr CorePatches::currentGameWindow; - -std::shared_ptr CorePatches::currentGameWindowCallbacks; +CorePatches::GameWindowHandle CorePatches::currentGameWindowHandle; void CorePatches::install(void* handle) { // void* ptr = linker::dlsym(handle, "_ZN3web4http6client7details35verify_cert_chain_platform_specificERN5boost4asio3ssl14verify_contextERKSs"); @@ -24,21 +22,61 @@ void CorePatches::install(void* handle) { } void CorePatches::showMousePointer() { - currentGameWindow->setCursorDisabled(false); + currentGameWindowHandle.mouseLocked = false; + currentGameWindowHandle.callbacks->setCursorLocked(false); } void CorePatches::hideMousePointer() { - currentGameWindow->setCursorDisabled(true); + currentGameWindowHandle.mouseLocked = true; + currentGameWindowHandle.callbacks->setCursorLocked(true); } void CorePatches::setFullscreen(void* t, bool fullscreen) { - currentGameWindowCallbacks->setFullscreen(fullscreen); + currentGameWindowHandle.callbacks->setFullscreen(fullscreen); } void CorePatches::setGameWindow(std::shared_ptr gameWindow) { - currentGameWindow = gameWindow; + currentGameWindowHandle.window = gameWindow; } void CorePatches::setGameWindowCallbacks(std::shared_ptr gameWindowCallbacks) { - currentGameWindowCallbacks = gameWindowCallbacks; -} \ No newline at end of file + currentGameWindowHandle.callbacks = gameWindowCallbacks; +} + +void CorePatches::loadGameWindowLibrary() { + std::unordered_map syms; + + syms["gamewindow_getprimarywindow"] = (void*)+[]() -> GameWindowHandle* { + return ¤tGameWindowHandle; + }; + + syms["gamewindow_ismouselocked"] = (void*)+[](GameWindowHandle* handle) -> bool { + return handle->mouseLocked; + }; + + syms["gamewindow_getinputmode"] = (void*)+[](GameWindowHandle* handle) -> int { + return (int)handle->callbacks->inputMode; + }; + + syms["gamewindow_sendkey"] = (void*)+[](GameWindowHandle* handle, int key, int action) { + handle->callbacks->onKeyboard((KeyCode)key, (KeyAction)action); + }; + + syms["gamewindow_addkeyboardinputhook"] = (void*)+[](GameWindowHandle* handle, void* user, bool (*hook)(void* user, int keyCode, int action)) { + handle->callbacks->addKeyboardHook(user, hook); + }; + + syms["gamewindow_addmouseclickhook"] = (void*)+[](GameWindowHandle* handle, void* user, bool (*hook)(void* user, double x, double y, int button, int action)) { + handle->callbacks->addMouseClickHook(user, hook); + }; + + syms["gamewindow_addmousepositionhook"] = (void*)+[](GameWindowHandle* handle, void* user, bool (*hook)(void* user, double x, double y, bool relative)) { + handle->callbacks->addMousePositionHook(user, hook); + }; + + syms["gamewindow_addmousescrollhook"] = (void*)+[](GameWindowHandle* handle, void* user, bool (*hook)(void* user, double x, double y, double dx, double dy)) { + handle->callbacks->addMouseScrollHook(user, hook); + }; + + linker::load_library("libmcpelauncher_gamewindow.so", syms); +} diff --git a/src/core_patches.h b/src/core_patches.h index 1ee052a4..6a4fb30f 100644 --- a/src/core_patches.h +++ b/src/core_patches.h @@ -6,12 +6,17 @@ class CorePatches { private: - static std::shared_ptr currentGameWindow; + struct GameWindowHandle { + std::shared_ptr window; + std::shared_ptr callbacks; + bool mouseLocked = false; + }; - static std::shared_ptr currentGameWindowCallbacks; + static GameWindowHandle currentGameWindowHandle; public: - static void install(void *handle); + static void + install(void* handle); static void showMousePointer(); @@ -22,4 +27,6 @@ class CorePatches { static void setGameWindow(std::shared_ptr gameWindow); static void setGameWindowCallbacks(std::shared_ptr gameWindowCallbacks); + + static void loadGameWindowLibrary(); }; diff --git a/src/jni/main_activity.cpp b/src/jni/main_activity.cpp index 01e728c5..5b959060 100644 --- a/src/jni/main_activity.cpp +++ b/src/jni/main_activity.cpp @@ -18,6 +18,7 @@ #include #include #include +#include "../core_patches.h" #include @@ -176,13 +177,13 @@ void MainActivity::requestIntegrityToken(std::shared_ptr str) void MainActivity::launchUri(std::shared_ptr url) { int pid; - if ((pid = fork())) { + if((pid = fork())) { } else { - #ifdef __APPLE__ +#ifdef __APPLE__ execl("/usr/bin/open", "/usr/bin/open", url->asStdString().c_str(), NULL); - #else +#else execl("/usr/bin/xdg-open", "/usr/bin/xdg-open", url->asStdString().c_str(), NULL); - #endif +#endif _Exit(0); } } @@ -192,15 +193,15 @@ void MainActivity::setClipboard(std::shared_ptr tocopy) { } void MainActivity::share(std::shared_ptr title, std::shared_ptr string, std::shared_ptr url) { - if ((title->asStdString().find("\"") == std::string::npos) && (title->asStdString().find("\\") == std::string::npos) && (string->asStdString().find("\"") == std::string::npos) && (string->asStdString().find("\\") == std::string::npos)) { + if((title->asStdString().find("\"") == std::string::npos) && (title->asStdString().find("\\") == std::string::npos) && (string->asStdString().find("\"") == std::string::npos) && (string->asStdString().find("\\") == std::string::npos)) { int pid; - if ((pid = fork())) { + if((pid = fork())) { } else { - #ifdef __APPLE__ +#ifdef __APPLE__ execl("/usr/bin/osascript", "/usr/bin/osascript", "-e", ("display alert \"" + title->asStdString() + "\" message \"" + string->asStdString() + "\n" + url->asStdString() + "\"").c_str(), NULL); - #else +#else execl("/usr/bin/zenity", "/usr/bin/zenity", "--info", "--title", title->asStdString().c_str(), "--text", (string->asStdString() + "\n" + url->asStdString()).c_str(), NULL); - #endif +#endif _Exit(0); } } @@ -334,8 +335,7 @@ FakeJni::JInt MainActivity::getKeyFromKeyCode(FakeJni::JInt keyCode, FakeJni::JI return 0; } auto ret = lastChar; - switch (keyCode) - { + switch(keyCode) { case AKEYCODE_DEL: case AKEYCODE_FORWARD_DEL: case AKEYCODE_SHIFT_LEFT: @@ -370,3 +370,11 @@ FakeJni::JInt MainActivity::getKeyFromKeyCode(FakeJni::JInt keyCode, FakeJni::JI void MainActivity::setLastChar(FakeJni::JInt sym) { lastChar = sym; } + +void MainActivity::lockCursor() { + CorePatches::hideMousePointer(); +} + +void MainActivity::unlockCursor() { + CorePatches::showMousePointer(); +} \ No newline at end of file diff --git a/src/jni/main_activity.h b/src/jni/main_activity.h index 20080b4b..b31c0519 100644 --- a/src/jni/main_activity.h +++ b/src/jni/main_activity.h @@ -81,11 +81,11 @@ class HardwareInfo : public FakeJni::JObject { DEFINE_CLASS_NAME("com/mojang/minecraftpe/HardwareInformation") static std::shared_ptr getAndroidVersion() { - #ifdef __APPLE__ +#ifdef __APPLE__ return std::make_shared("macOS"); - #else +#else return std::make_shared("Linux"); - #endif +#endif } std::shared_ptr getInstallerPackageName() { @@ -152,11 +152,11 @@ class MainActivity : public NativeActivity { } std::shared_ptr getDeviceModel() { - #ifdef __APPLE__ +#ifdef __APPLE__ return std::make_shared("macOS"); - #else +#else return std::make_shared("Linux"); - #endif +#endif } std::shared_ptr getFilesDir() override { @@ -203,7 +203,6 @@ class MainActivity : public NativeActivity { auto method = getClass().getMethod("(J)V", "nativeRunNativeCallbackOnUiThread"); FakeJni::LocalFrame frame; method->invoke(frame.getJniEnv(), this, h); - } void requestIntegrityToken(std::shared_ptr); @@ -262,13 +261,9 @@ class MainActivity : public NativeActivity { FakeJni::JInt getCaretPosition(); - void lockCursor() { - window->setCursorDisabled(true); - } + void lockCursor(); - void unlockCursor() { - window->setCursorDisabled(false); - } + void unlockCursor(); FakeJni::JLong getUsedMemory(); diff --git a/src/main.cpp b/src/main.cpp index e1409347..ac49ac06 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -371,6 +371,8 @@ Hardware : Qualcomm Technologies, Inc MSM8998 for(auto s = android_symbols; *s; s++) // stub missing symbols android_syms.insert({*s, (void*)+[]() { Log::warn("Main", "Android stub called"); }}); linker::load_library("libandroid.so", android_syms); + CorePatches::loadGameWindowLibrary(); + linker::load_library("libmcpelauncher_menu.so", { { "mcpelauncher_addmenu", (void*)mcpelauncher_addmenu }, diff --git a/src/window_callbacks.cpp b/src/window_callbacks.cpp index e643f40f..c8ffadff 100644 --- a/src/window_callbacks.cpp +++ b/src/window_callbacks.cpp @@ -30,7 +30,7 @@ static int ReadEnvInt(const char* name, int def = 0) { WindowCallbacks::WindowCallbacks(GameWindow& window, JniSupport& jniSupport, FakeInputQueue& inputQueue) : window(window), jniSupport(jniSupport), inputQueue(inputQueue) { useDirectMouseInput = Mouse::feed; useDirectKeyboardInput = (Keyboard::_states && (Keyboard::_inputs || Keyboard::_inputsLegacy) && Keyboard::_gameControllerId); - if (Settings::fullscreen) { + if(Settings::fullscreen) { window.setFullscreen(true); } useRawInput = ReadEnvFlag("MCPELAUNCHER_CLIENT_RAW_INPUT"); @@ -61,7 +61,7 @@ void WindowCallbacks::registerCallbacks() { void WindowCallbacks::startSendEvents() { if(!sendEvents) { sendEvents = true; - for(auto && gp : gamepads) { + for(auto&& gp : gamepads) { jniSupport.setGameControllerConnected(gp.first, true); } } @@ -77,6 +77,12 @@ void WindowCallbacks::onWindowSizeCallback(int w, int h) { jniSupport.onWindowResized(w, h - Settings::menubarsize); } +void WindowCallbacks::setCursorLocked(bool locked) { + cursorLocked = locked; + if(hasInputMode(InputMode::Mouse, false)) + window.setCursorDisabled(locked); +} + void WindowCallbacks::onClose() { jniSupport.onWindowClosed(); } @@ -120,6 +126,15 @@ bool WindowCallbacks::hasInputMode(WindowCallbacks::InputMode want, bool changeM void WindowCallbacks::onMouseButton(double x, double y, int btn, MouseButtonAction action) { if(hasInputMode(InputMode::Mouse)) { + if(mouseClickHooksLock.try_lock()) { + for(size_t i = 0; i < mouseClickHooks.size(); i++) { + if(mouseClickHooks[i].hook(mouseClickHooks[i].user, x, y, (int)btn, (int)action)) { + mouseClickHooksLock.unlock(); + return; + } + } + mouseClickHooksLock.unlock(); + } if(btn < 1) return; #ifdef USE_IMGUI @@ -147,7 +162,7 @@ void WindowCallbacks::onMouseButton(double x, double y, int btn, MouseButtonActi if(useDirectMouseInput) Mouse::feed((char)btn, (char)(action == MouseButtonAction::PRESS ? 1 : 0), (short)x, (short)y, 0, 0); else if(action == MouseButtonAction::PRESS) { - buttonState|=mapMouseButtonToAndroid(btn); + buttonState |= mapMouseButtonToAndroid(btn); inputQueue.addEvent(FakeMotionEvent(AINPUT_SOURCE_MOUSE, AMOTION_EVENT_ACTION_BUTTON_PRESS, 0, x, y - Settings::menubarsize, buttonState, 0)); } else if(action == MouseButtonAction::RELEASE) { buttonState = buttonState & ~mapMouseButtonToAndroid(btn); @@ -157,8 +172,17 @@ void WindowCallbacks::onMouseButton(double x, double y, int btn, MouseButtonActi } void WindowCallbacks::onMousePosition(double x, double y) { if(hasInputMode(InputMode::Mouse)) { + if(mousePositionHooksLock.try_lock()) { + for(size_t i = 0; i < mousePositionHooks.size(); i++) { + if(mousePositionHooks[i].hook(mousePositionHooks[i].user, x, y, false)) { + mousePositionHooksLock.unlock(); + return; + } + } + mousePositionHooksLock.unlock(); + } #ifdef USE_IMGUI - if(ImGui::GetCurrentContext()) { + if(ImGui::GetCurrentContext()) { ImGuiIO& io = ImGui::GetIO(); io.AddMouseSourceEvent(ImGuiMouseSource_Mouse); io.AddMousePosEvent(x, y); @@ -175,6 +199,15 @@ void WindowCallbacks::onMousePosition(double x, double y) { } void WindowCallbacks::onMouseRelativePosition(double x, double y) { if(hasInputMode(InputMode::Mouse, std::abs(x) > 10 || std::abs(y) > 10)) { + if(mousePositionHooksLock.try_lock()) { + for(size_t i = 0; i < mousePositionHooks.size(); i++) { + if(mousePositionHooks[i].hook(mousePositionHooks[i].user, x, y, true)) { + mousePositionHooksLock.unlock(); + return; + } + } + mousePositionHooksLock.unlock(); + } if(useDirectMouseInput) Mouse::feed(0, 0, 0, 0, (short)x, (short)y); else @@ -183,6 +216,15 @@ void WindowCallbacks::onMouseRelativePosition(double x, double y) { } void WindowCallbacks::onMouseScroll(double x, double y, double dx, double dy) { if(hasInputMode(InputMode::Mouse)) { + if(mouseScrollHooksLock.try_lock()) { + for(size_t i = 0; i < mouseScrollHooks.size(); i++) { + if(mouseScrollHooks[i].hook(mouseScrollHooks[i].user, x, y, dx, dy)) { + mouseScrollHooksLock.unlock(); + return; + } + } + mouseScrollHooksLock.unlock(); + } #ifdef USE_IMGUI if(ImGui::GetCurrentContext()) { ImGuiIO& io = ImGui::GetIO(); @@ -250,8 +292,7 @@ void WindowCallbacks::onTouchEnd(int id, double x, double y) { } } static bool deadKey(KeyCode key) { - switch (WindowCallbacks::mapMinecraftToAndroidKey(key)) - { + switch(WindowCallbacks::mapMinecraftToAndroidKey(key)) { case AKEYCODE_DEL: case AKEYCODE_FORWARD_DEL: case AKEYCODE_SHIFT_LEFT: @@ -402,6 +443,15 @@ static ImGuiKey mapImGuiModKey(KeyCode code) { void WindowCallbacks::onKeyboard(KeyCode key, KeyAction action) { if(hasInputMode(InputMode::Mouse)) { + if(keyboardHooksLock.try_lock()) { + for(size_t i = 0; i < keyboardHooks.size(); i++) { + if(keyboardHooks[i].hook(keyboardHooks[i].user, (int)key, (int)action)) { + keyboardHooksLock.unlock(); + return; + } + } + keyboardHooksLock.unlock(); + } #ifdef USE_IMGUI if(ImGui::GetCurrentContext()) { ImGuiIO& io = ImGui::GetIO(); @@ -439,7 +489,7 @@ void WindowCallbacks::onKeyboard(KeyCode key, KeyAction action) { setFullscreen(!Settings::fullscreen); if(useDirectKeyboardInput && (action == KeyAction::PRESS || action == KeyAction::RELEASE)) { - if (Keyboard::useLegacyKeyboard) { + if(Keyboard::useLegacyKeyboard) { Keyboard::LegacyInputEvent evData{}; evData.key = (unsigned int)key & 0xff; evData.event = (action == KeyAction::PRESS ? 1 : 0); @@ -461,8 +511,7 @@ void WindowCallbacks::onKeyboard(KeyCode key, KeyAction action) { } int32_t state = 0; - switch (key) - { + switch(key) { case KeyCode::LEFT_SHIFT: state |= AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON; break; @@ -482,7 +531,7 @@ void WindowCallbacks::onKeyboard(KeyCode key, KeyAction action) { state |= AMETA_CTRL_RIGHT_ON | AMETA_CTRL_ON; break; case KeyCode::LEFT_SUPER: - state |= AMETA_META_LEFT_ON| AMETA_META_ON; + state |= AMETA_META_LEFT_ON | AMETA_META_ON; break; case KeyCode::RIGHT_SUPER: state |= AMETA_META_RIGHT_ON | AMETA_META_ON; @@ -501,7 +550,7 @@ void WindowCallbacks::onKeyboard(KeyCode key, KeyAction action) { if(Settings::enable_keyboard_tab_patches_1_20_60 && state == 0) { if(jniSupport.getTextInputHandler().isEnabled() && !jniSupport.getTextInputHandler().isMultiline()) { - if(action == KeyAction::PRESS && (lastKey == KeyCode::TAB || lastKey == KeyCode::UP || lastKey == KeyCode::DOWN) && !(key == KeyCode::TAB || key == KeyCode::UP || key == KeyCode::DOWN || key == KeyCode::ENTER|| key == KeyCode::ESCAPE) && lastEnabledNo == jniSupport.getTextInputHandler().getEnabledNo()) { + if(action == KeyAction::PRESS && (lastKey == KeyCode::TAB || lastKey == KeyCode::UP || lastKey == KeyCode::DOWN) && !(key == KeyCode::TAB || key == KeyCode::UP || key == KeyCode::DOWN || key == KeyCode::ENTER || key == KeyCode::ESCAPE) && lastEnabledNo == jniSupport.getTextInputHandler().getEnabledNo()) { if(!deadKey(key)) { jniSupport.getTextInputHandler().setKeepLastCharOnce(); } @@ -636,6 +685,30 @@ void WindowCallbacks::onGamepadAxis(int gamepad, GamepadAxisId ax, float value) } } +void WindowCallbacks::addKeyboardHook(void* user, bool (*hook)(void* user, int keyCode, int action)) { + keyboardHooksLock.lock(); + keyboardHooks.emplace_back(KeyboardInputHook{.user = user, .hook = hook}); + keyboardHooksLock.unlock(); +} + +void WindowCallbacks::addMouseClickHook(void* user, bool (*hook)(void* user, double x, double y, int button, int action)) { + mouseClickHooksLock.lock(); + mouseClickHooks.emplace_back(MouseClickHook{.user = user, .hook = hook}); + mouseClickHooksLock.unlock(); +} + +void WindowCallbacks::addMousePositionHook(void* user, bool (*hook)(void* user, double x, double y, bool relative)) { + mousePositionHooksLock.lock(); + mousePositionHooks.emplace_back(MousePositionHook{.user = user, .hook = hook}); + mousePositionHooksLock.unlock(); +} + +void WindowCallbacks::addMouseScrollHook(void* user, bool (*hook)(void* user, double x, double y, double dx, double dy)) { + mouseScrollHooksLock.lock(); + mouseScrollHooks.emplace_back(MouseScrollHook{.user = user, .hook = hook}); + mouseScrollHooksLock.unlock(); +} + void WindowCallbacks::loadGamepadMappings() { auto windowManager = GameWindowManager::getManager(); std::vector controllerDbPaths; @@ -658,11 +731,16 @@ WindowCallbacks::GamepadData::GamepadData() { int WindowCallbacks::mapMouseButtonToAndroid(int btn) { switch(btn) { - case 1: return AMOTION_EVENT_BUTTON_PRIMARY; - case 2: return AMOTION_EVENT_BUTTON_SECONDARY; - case 3: return AMOTION_EVENT_BUTTON_TERTIARY; - case 8: return AMOTION_EVENT_BUTTON_BACK; - case 9: return AMOTION_EVENT_BUTTON_FORWARD; + case 1: + return AMOTION_EVENT_BUTTON_PRIMARY; + case 2: + return AMOTION_EVENT_BUTTON_SECONDARY; + case 3: + return AMOTION_EVENT_BUTTON_TERTIARY; + case 8: + return AMOTION_EVENT_BUTTON_BACK; + case 9: + return AMOTION_EVENT_BUTTON_FORWARD; } return btn; } diff --git a/src/window_callbacks.h b/src/window_callbacks.h index 97075caa..4c50168a 100644 --- a/src/window_callbacks.h +++ b/src/window_callbacks.h @@ -5,6 +5,8 @@ #include "jni/jni_support.h" #include "fake_inputqueue.h" #include +#include +#include #include "main.h" #ifdef USE_IMGUI #include @@ -17,6 +19,31 @@ class WindowCallbacks { GamepadData(); }; + struct KeyboardInputHook { + void *user; + bool (*hook)(void *user, int keyCode, int action); + }; + struct MouseClickHook { + void *user; + bool (*hook)(void *user, double x, double y, int button, int action); + }; + struct MousePositionHook { + void *user; + bool (*hook)(void *user, double x, double y, bool relative); + }; + struct MouseScrollHook { + void *user; + bool (*hook)(void *user, double x, double y, double dx, double dy); + }; + + std::vector keyboardHooks; + std::vector mouseClickHooks; + std::vector mousePositionHooks; + std::vector mouseScrollHooks; + std::mutex keyboardHooksLock; + std::mutex mouseClickHooksLock; + std::mutex mousePositionHooksLock; + std::mutex mouseScrollHooksLock; GameWindow &window; JniSupport &jniSupport; @@ -30,6 +57,7 @@ class WindowCallbacks { bool modCTRL = false; bool needsQueueGamepadInput = true; bool sendEvents = false; + bool cursorLocked = false; bool imguiTextInput = false; int menubarsize = 0; enum class InputMode { @@ -42,7 +70,6 @@ class WindowCallbacks { bool useRawInput = false; InputMode forcedMode = InputMode::Unknown; int inputModeSwitchDelay = 100; - InputMode inputMode = InputMode::Unknown; std::chrono::high_resolution_clock::time_point lastUpdated; bool hasInputMode(InputMode want = InputMode::Unknown, bool changeMode = true); @@ -61,6 +88,8 @@ class WindowCallbacks { void onWindowSizeCallback(int w, int h); + void setCursorLocked(bool locked); + void onClose(); void setFullscreen(bool isFs); @@ -79,9 +108,16 @@ class WindowCallbacks { void onGamepadButton(int gamepad, GamepadButtonId btn, bool pressed); void onGamepadAxis(int gamepad, GamepadAxisId ax, float value); + void addKeyboardHook(void *user, bool (*hook)(void *user, int keyCode, int action)); + void addMouseClickHook(void *user, bool (*hook)(void *user, double x, double y, int button, int action)); + void addMousePositionHook(void *user, bool (*hook)(void *user, double x, double y, bool relative)); + void addMouseScrollHook(void *user, bool (*hook)(void *user, double x, double y, double dx, double dy)); + static int mapMouseButtonToAndroid(int btn); static int mapMinecraftToAndroidKey(KeyCode code); static int mapGamepadToAndroidKey(GamepadButtonId btn); + + InputMode inputMode = InputMode::Unknown; #ifdef USE_IMGUI static ImGuiKey mapImGuiKey(KeyCode code); #endif From 9dc9df6dac4e8a7d2176c49e4d4b4604166b90e3 Mon Sep 17 00:00:00 2001 From: GameParrot <85067619+GameParrot@users.noreply.github.com> Date: Fri, 27 Dec 2024 16:05:12 -0500 Subject: [PATCH 2/4] add gamewindow_addwindowcreationcallback --- src/core_patches.cpp | 8 ++++++++ src/core_patches.h | 3 +++ 2 files changed, 11 insertions(+) diff --git a/src/core_patches.cpp b/src/core_patches.cpp index 213b17d2..98077055 100644 --- a/src/core_patches.cpp +++ b/src/core_patches.cpp @@ -5,6 +5,7 @@ #include CorePatches::GameWindowHandle CorePatches::currentGameWindowHandle; +std::vector> CorePatches::onWindowCreatedCallbacks; void CorePatches::install(void* handle) { // void* ptr = linker::dlsym(handle, "_ZN3web4http6client7details35verify_cert_chain_platform_specificERN5boost4asio3ssl14verify_contextERKSs"); @@ -41,6 +42,9 @@ void CorePatches::setGameWindow(std::shared_ptr gameWindow) { void CorePatches::setGameWindowCallbacks(std::shared_ptr gameWindowCallbacks) { currentGameWindowHandle.callbacks = gameWindowCallbacks; + for(size_t i = 0; i < onWindowCreatedCallbacks.size(); i++) { + onWindowCreatedCallbacks[i](); + } } void CorePatches::loadGameWindowLibrary() { @@ -78,5 +82,9 @@ void CorePatches::loadGameWindowLibrary() { handle->callbacks->addMouseScrollHook(user, hook); }; + syms["gamewindow_addwindowcreationcallback"] = (void*)+[](void* user, void (*onCreated)(void* user)) { + onWindowCreatedCallbacks.emplace_back(std::bind(onCreated, user)); + }; + linker::load_library("libmcpelauncher_gamewindow.so", syms); } diff --git a/src/core_patches.h b/src/core_patches.h index 6a4fb30f..1bb38e5f 100644 --- a/src/core_patches.h +++ b/src/core_patches.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include "window_callbacks.h" @@ -14,6 +15,8 @@ class CorePatches { static GameWindowHandle currentGameWindowHandle; + static std::vector> onWindowCreatedCallbacks; + public: static void install(void* handle); From 30a9e6516f64b3783395692a3b1451f9dacb1388 Mon Sep 17 00:00:00 2001 From: GameParrot <85067619+GameParrot@users.noreply.github.com> Date: Fri, 27 Dec 2024 19:15:28 -0500 Subject: [PATCH 3/4] rename --- src/core_patches.cpp | 30 ++++++-------- src/window_callbacks.cpp | 86 +++++++++++++++++++++------------------- src/window_callbacks.h | 45 +++++++++++---------- 3 files changed, 81 insertions(+), 80 deletions(-) diff --git a/src/core_patches.cpp b/src/core_patches.cpp index 98077055..adc13a73 100644 --- a/src/core_patches.cpp +++ b/src/core_patches.cpp @@ -50,39 +50,35 @@ void CorePatches::setGameWindowCallbacks(std::shared_ptr gameWi void CorePatches::loadGameWindowLibrary() { std::unordered_map syms; - syms["gamewindow_getprimarywindow"] = (void*)+[]() -> GameWindowHandle* { + syms["game_window_get_primary_window"] = (void*)+[]() -> GameWindowHandle* { return ¤tGameWindowHandle; }; - syms["gamewindow_ismouselocked"] = (void*)+[](GameWindowHandle* handle) -> bool { + syms["game_window_is_mouse_locked"] = (void*)+[](GameWindowHandle* handle) -> bool { return handle->mouseLocked; }; - syms["gamewindow_getinputmode"] = (void*)+[](GameWindowHandle* handle) -> int { - return (int)handle->callbacks->inputMode; + syms["game_window_get_input_mode"] = (void*)+[](GameWindowHandle* handle) -> int { + return (int)handle->callbacks->getInputMode(); }; - syms["gamewindow_sendkey"] = (void*)+[](GameWindowHandle* handle, int key, int action) { - handle->callbacks->onKeyboard((KeyCode)key, (KeyAction)action); + syms["game_window_add_keyboard_callback"] = (void*)+[](GameWindowHandle* handle, void* user, bool (*callback)(void* user, int keyCode, int action)) { + handle->callbacks->addKeyboardCallback(user, callback); }; - syms["gamewindow_addkeyboardinputhook"] = (void*)+[](GameWindowHandle* handle, void* user, bool (*hook)(void* user, int keyCode, int action)) { - handle->callbacks->addKeyboardHook(user, hook); + syms["game_window_add_mouse_button_callback"] = (void*)+[](GameWindowHandle* handle, void* user, bool (*callback)(void* user, double x, double y, int button, int action)) { + handle->callbacks->addMouseButtonCallback(user, callback); }; - syms["gamewindow_addmouseclickhook"] = (void*)+[](GameWindowHandle* handle, void* user, bool (*hook)(void* user, double x, double y, int button, int action)) { - handle->callbacks->addMouseClickHook(user, hook); + syms["game_window_add_mouse_position_callback"] = (void*)+[](GameWindowHandle* handle, void* user, bool (*callback)(void* user, double x, double y, bool relative)) { + handle->callbacks->addMousePositionCallback(user, callback); }; - syms["gamewindow_addmousepositionhook"] = (void*)+[](GameWindowHandle* handle, void* user, bool (*hook)(void* user, double x, double y, bool relative)) { - handle->callbacks->addMousePositionHook(user, hook); + syms["game_window_add_mouse_scroll_callback"] = (void*)+[](GameWindowHandle* handle, void* user, bool (*callback)(void* user, double x, double y, double dx, double dy)) { + handle->callbacks->addMouseScrollCallback(user, callback); }; - syms["gamewindow_addmousescrollhook"] = (void*)+[](GameWindowHandle* handle, void* user, bool (*hook)(void* user, double x, double y, double dx, double dy)) { - handle->callbacks->addMouseScrollHook(user, hook); - }; - - syms["gamewindow_addwindowcreationcallback"] = (void*)+[](void* user, void (*onCreated)(void* user)) { + syms["game_window_add_window_creation_callback"] = (void*)+[](void* user, void (*onCreated)(void* user)) { onWindowCreatedCallbacks.emplace_back(std::bind(onCreated, user)); }; diff --git a/src/window_callbacks.cpp b/src/window_callbacks.cpp index c8ffadff..14e460bb 100644 --- a/src/window_callbacks.cpp +++ b/src/window_callbacks.cpp @@ -95,6 +95,10 @@ void WindowCallbacks::setFullscreen(bool isFs) { } } +WindowCallbacks::InputMode WindowCallbacks::getInputMode() { + return inputMode; +} + bool WindowCallbacks::hasInputMode(WindowCallbacks::InputMode want, bool changeMode) { if(!sendEvents) { return false; @@ -126,14 +130,14 @@ bool WindowCallbacks::hasInputMode(WindowCallbacks::InputMode want, bool changeM void WindowCallbacks::onMouseButton(double x, double y, int btn, MouseButtonAction action) { if(hasInputMode(InputMode::Mouse)) { - if(mouseClickHooksLock.try_lock()) { - for(size_t i = 0; i < mouseClickHooks.size(); i++) { - if(mouseClickHooks[i].hook(mouseClickHooks[i].user, x, y, (int)btn, (int)action)) { - mouseClickHooksLock.unlock(); + if(mouseButtonCallbacksLock.try_lock()) { + for(size_t i = 0; i < mouseButtonCallbacks.size(); i++) { + if(mouseButtonCallbacks[i].callback(mouseButtonCallbacks[i].user, x, y, (int)btn, (int)action)) { + mouseButtonCallbacksLock.unlock(); return; } } - mouseClickHooksLock.unlock(); + mouseButtonCallbacksLock.unlock(); } if(btn < 1) return; @@ -172,14 +176,14 @@ void WindowCallbacks::onMouseButton(double x, double y, int btn, MouseButtonActi } void WindowCallbacks::onMousePosition(double x, double y) { if(hasInputMode(InputMode::Mouse)) { - if(mousePositionHooksLock.try_lock()) { - for(size_t i = 0; i < mousePositionHooks.size(); i++) { - if(mousePositionHooks[i].hook(mousePositionHooks[i].user, x, y, false)) { - mousePositionHooksLock.unlock(); + if(mousePositionCallbacksLock.try_lock()) { + for(size_t i = 0; i < mousePositionCallbacks.size(); i++) { + if(mousePositionCallbacks[i].callback(mousePositionCallbacks[i].user, x, y, false)) { + mousePositionCallbacksLock.unlock(); return; } } - mousePositionHooksLock.unlock(); + mousePositionCallbacksLock.unlock(); } #ifdef USE_IMGUI if(ImGui::GetCurrentContext()) { @@ -199,14 +203,14 @@ void WindowCallbacks::onMousePosition(double x, double y) { } void WindowCallbacks::onMouseRelativePosition(double x, double y) { if(hasInputMode(InputMode::Mouse, std::abs(x) > 10 || std::abs(y) > 10)) { - if(mousePositionHooksLock.try_lock()) { - for(size_t i = 0; i < mousePositionHooks.size(); i++) { - if(mousePositionHooks[i].hook(mousePositionHooks[i].user, x, y, true)) { - mousePositionHooksLock.unlock(); + if(mousePositionCallbacksLock.try_lock()) { + for(size_t i = 0; i < mousePositionCallbacks.size(); i++) { + if(mousePositionCallbacks[i].callback(mousePositionCallbacks[i].user, x, y, true)) { + mousePositionCallbacksLock.unlock(); return; } } - mousePositionHooksLock.unlock(); + mousePositionCallbacksLock.unlock(); } if(useDirectMouseInput) Mouse::feed(0, 0, 0, 0, (short)x, (short)y); @@ -216,14 +220,14 @@ void WindowCallbacks::onMouseRelativePosition(double x, double y) { } void WindowCallbacks::onMouseScroll(double x, double y, double dx, double dy) { if(hasInputMode(InputMode::Mouse)) { - if(mouseScrollHooksLock.try_lock()) { - for(size_t i = 0; i < mouseScrollHooks.size(); i++) { - if(mouseScrollHooks[i].hook(mouseScrollHooks[i].user, x, y, dx, dy)) { - mouseScrollHooksLock.unlock(); + if(mouseScrollCallbacksLock.try_lock()) { + for(size_t i = 0; i < mouseScrollCallbacks.size(); i++) { + if(mouseScrollCallbacks[i].callback(mouseScrollCallbacks[i].user, x, y, dx, dy)) { + mouseScrollCallbacksLock.unlock(); return; } } - mouseScrollHooksLock.unlock(); + mouseScrollCallbacksLock.unlock(); } #ifdef USE_IMGUI if(ImGui::GetCurrentContext()) { @@ -443,14 +447,14 @@ static ImGuiKey mapImGuiModKey(KeyCode code) { void WindowCallbacks::onKeyboard(KeyCode key, KeyAction action) { if(hasInputMode(InputMode::Mouse)) { - if(keyboardHooksLock.try_lock()) { - for(size_t i = 0; i < keyboardHooks.size(); i++) { - if(keyboardHooks[i].hook(keyboardHooks[i].user, (int)key, (int)action)) { - keyboardHooksLock.unlock(); + if(keyboardCallbacksLock.try_lock()) { + for(size_t i = 0; i < keyboardCallbacks.size(); i++) { + if(keyboardCallbacks[i].callback(keyboardCallbacks[i].user, (int)key, (int)action)) { + keyboardCallbacksLock.unlock(); return; } } - keyboardHooksLock.unlock(); + keyboardCallbacksLock.unlock(); } #ifdef USE_IMGUI if(ImGui::GetCurrentContext()) { @@ -685,28 +689,28 @@ void WindowCallbacks::onGamepadAxis(int gamepad, GamepadAxisId ax, float value) } } -void WindowCallbacks::addKeyboardHook(void* user, bool (*hook)(void* user, int keyCode, int action)) { - keyboardHooksLock.lock(); - keyboardHooks.emplace_back(KeyboardInputHook{.user = user, .hook = hook}); - keyboardHooksLock.unlock(); +void WindowCallbacks::addKeyboardCallback(void* user, bool (*callback)(void* user, int keyCode, int action)) { + keyboardCallbacksLock.lock(); + keyboardCallbacks.emplace_back(KeyboardInputCallback{.user = user, .callback = callback}); + keyboardCallbacksLock.unlock(); } -void WindowCallbacks::addMouseClickHook(void* user, bool (*hook)(void* user, double x, double y, int button, int action)) { - mouseClickHooksLock.lock(); - mouseClickHooks.emplace_back(MouseClickHook{.user = user, .hook = hook}); - mouseClickHooksLock.unlock(); +void WindowCallbacks::addMouseButtonCallback(void* user, bool (*callback)(void* user, double x, double y, int button, int action)) { + mouseButtonCallbacksLock.lock(); + mouseButtonCallbacks.emplace_back(MouseButtonCallback{.user = user, .callback = callback}); + mouseButtonCallbacksLock.unlock(); } -void WindowCallbacks::addMousePositionHook(void* user, bool (*hook)(void* user, double x, double y, bool relative)) { - mousePositionHooksLock.lock(); - mousePositionHooks.emplace_back(MousePositionHook{.user = user, .hook = hook}); - mousePositionHooksLock.unlock(); +void WindowCallbacks::addMousePositionCallback(void* user, bool (*callback)(void* user, double x, double y, bool relative)) { + mousePositionCallbacksLock.lock(); + mousePositionCallbacks.emplace_back(MousePositionCallback{.user = user, .callback = callback}); + mousePositionCallbacksLock.unlock(); } -void WindowCallbacks::addMouseScrollHook(void* user, bool (*hook)(void* user, double x, double y, double dx, double dy)) { - mouseScrollHooksLock.lock(); - mouseScrollHooks.emplace_back(MouseScrollHook{.user = user, .hook = hook}); - mouseScrollHooksLock.unlock(); +void WindowCallbacks::addMouseScrollCallback(void* user, bool (*callback)(void* user, double x, double y, double dx, double dy)) { + mouseScrollCallbacksLock.lock(); + mouseScrollCallbacks.emplace_back(MouseScrollCallback{.user = user, .callback = callback}); + mouseScrollCallbacksLock.unlock(); } void WindowCallbacks::loadGamepadMappings() { diff --git a/src/window_callbacks.h b/src/window_callbacks.h index 4c50168a..49c3a3e8 100644 --- a/src/window_callbacks.h +++ b/src/window_callbacks.h @@ -19,31 +19,31 @@ class WindowCallbacks { GamepadData(); }; - struct KeyboardInputHook { + struct KeyboardInputCallback { void *user; - bool (*hook)(void *user, int keyCode, int action); + bool (*callback)(void *user, int keyCode, int action); }; - struct MouseClickHook { + struct MouseButtonCallback { void *user; - bool (*hook)(void *user, double x, double y, int button, int action); + bool (*callback)(void *user, double x, double y, int button, int action); }; - struct MousePositionHook { + struct MousePositionCallback { void *user; - bool (*hook)(void *user, double x, double y, bool relative); + bool (*callback)(void *user, double x, double y, bool relative); }; - struct MouseScrollHook { + struct MouseScrollCallback { void *user; - bool (*hook)(void *user, double x, double y, double dx, double dy); + bool (*callback)(void *user, double x, double y, double dx, double dy); }; - std::vector keyboardHooks; - std::vector mouseClickHooks; - std::vector mousePositionHooks; - std::vector mouseScrollHooks; - std::mutex keyboardHooksLock; - std::mutex mouseClickHooksLock; - std::mutex mousePositionHooksLock; - std::mutex mouseScrollHooksLock; + std::vector keyboardCallbacks; + std::vector mouseButtonCallbacks; + std::vector mousePositionCallbacks; + std::vector mouseScrollCallbacks; + std::mutex keyboardCallbacksLock; + std::mutex mouseButtonCallbacksLock; + std::mutex mousePositionCallbacksLock; + std::mutex mouseScrollCallbacksLock; GameWindow &window; JniSupport &jniSupport; @@ -68,6 +68,7 @@ class WindowCallbacks { }; int imGuiTouchId = -1; bool useRawInput = false; + InputMode inputMode = InputMode::Unknown; InputMode forcedMode = InputMode::Unknown; int inputModeSwitchDelay = 100; std::chrono::high_resolution_clock::time_point lastUpdated; @@ -94,6 +95,8 @@ class WindowCallbacks { void setFullscreen(bool isFs); + InputMode getInputMode(); + void onMouseButton(double x, double y, int btn, MouseButtonAction action); void onMousePosition(double x, double y); void onMouseRelativePosition(double x, double y); @@ -108,16 +111,14 @@ class WindowCallbacks { void onGamepadButton(int gamepad, GamepadButtonId btn, bool pressed); void onGamepadAxis(int gamepad, GamepadAxisId ax, float value); - void addKeyboardHook(void *user, bool (*hook)(void *user, int keyCode, int action)); - void addMouseClickHook(void *user, bool (*hook)(void *user, double x, double y, int button, int action)); - void addMousePositionHook(void *user, bool (*hook)(void *user, double x, double y, bool relative)); - void addMouseScrollHook(void *user, bool (*hook)(void *user, double x, double y, double dx, double dy)); + void addKeyboardCallback(void *user, bool (*callback)(void *user, int keyCode, int action)); + void addMouseButtonCallback(void *user, bool (*callback)(void *user, double x, double y, int button, int action)); + void addMousePositionCallback(void *user, bool (*callback)(void *user, double x, double y, bool relative)); + void addMouseScrollCallback(void *user, bool (*callback)(void *user, double x, double y, double dx, double dy)); static int mapMouseButtonToAndroid(int btn); static int mapMinecraftToAndroidKey(KeyCode code); static int mapGamepadToAndroidKey(GamepadButtonId btn); - - InputMode inputMode = InputMode::Unknown; #ifdef USE_IMGUI static ImGuiKey mapImGuiKey(KeyCode code); #endif From bb2d9d76f4fa47b961bf3e9990bbe13a8fe89728 Mon Sep 17 00:00:00 2001 From: GameParrot <85067619+GameParrot@users.noreply.github.com> Date: Fri, 27 Dec 2024 21:44:10 -0500 Subject: [PATCH 4/4] Give mods access to imgui context and draw callback --- src/imgui_ui.cpp | 18 ++++++++++++++++++ src/imgui_ui.h | 6 +++++- src/main.cpp | 2 ++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/imgui_ui.cpp b/src/imgui_ui.cpp index 7c781ec7..665ade54 100644 --- a/src/imgui_ui.cpp +++ b/src/imgui_ui.cpp @@ -177,6 +177,8 @@ static std::vector menuentries; static std::mutex menuentrieslock; static std::vector> activeWindows; static std::mutex activeWindowsLock; +static std::vector> onDrawCallbacks; +static std::mutex onDrawCallbacksLock; static void convertEntries(std::vector& menuentries, size_t length, MenuEntryABI* entries) { for(size_t i = 0; i < length; i++) { @@ -280,6 +282,16 @@ void mcpelauncher_close_window(const char *title) { activeWindowsLock.unlock(); } +void mcpelauncher_add_draw_callback(void* user, void(*onDraw)(void* user)) { + onDrawCallbacksLock.lock(); + onDrawCallbacks.push_back(std::bind(onDraw, user)); + onDrawCallbacksLock.unlock(); +} + +struct ImGuiContext* mcpelauncher_get_imgui_context() { + return ImGui::GetCurrentContext(); +} + void ImGuiUIInit(GameWindow* window) { if(!glGetString) { return; @@ -928,6 +940,12 @@ void ImGuiUIDrawFrame(GameWindow* window) { activeWindowsLock.unlock(); } + onDrawCallbacksLock.lock(); + for(size_t i = 0; i < onDrawCallbacks.size(); i++) { + onDrawCallbacks[i](); + } + onDrawCallbacksLock.unlock(); + // Rendering ImGui::Render(); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); diff --git a/src/imgui_ui.h b/src/imgui_ui.h index 58395c02..f38e6ffc 100644 --- a/src/imgui_ui.h +++ b/src/imgui_ui.h @@ -55,4 +55,8 @@ struct control }; void mcpelauncher_show_window(const char* title, int isModal, void* user, void(*onClose)(void* user), int count, control* controls); -void mcpelauncher_close_window(const char *title); \ No newline at end of file +void mcpelauncher_close_window(const char *title); + +void mcpelauncher_add_draw_callback(void* user, void(*onDraw)(void* user)); + +struct ImGuiContext* mcpelauncher_get_imgui_context(); \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index ac49ac06..827a25b2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -378,6 +378,8 @@ Hardware : Qualcomm Technologies, Inc MSM8998 { "mcpelauncher_addmenu", (void*)mcpelauncher_addmenu }, { "mcpelauncher_show_window", (void*)mcpelauncher_show_window }, { "mcpelauncher_close_window", (void*)mcpelauncher_close_window }, + { "mcpelauncher_add_draw_callback", (void*)mcpelauncher_add_draw_callback }, + { "mcpelauncher_get_imgui_context", (void*)mcpelauncher_get_imgui_context }, }); ModLoader modLoader;