From d7126a23a792432aeb92e687ce504a7b95861d13 Mon Sep 17 00:00:00 2001 From: Peter Vaassens Date: Thu, 11 Jun 2020 01:38:11 +0200 Subject: [PATCH 1/2] Workaround for vulcan renderer --- src/main/java/dev/tricht/lunaris/Lunaris.kt | 28 +++++-- .../lunaris/settings/general/GeneralGUI.java | 22 ++++++ .../platform/windows/VulkanFullscreenFixer.kt | 74 +++++++++++++++++++ .../platform/windows/WindowFocusListener.kt | 64 ++++++++++++++++ .../util/platform/windows/WindowsKeyboard.kt | 39 ++++++++++ .../resources/settings/general/general.fxml | 2 + 6 files changed, 224 insertions(+), 5 deletions(-) create mode 100644 src/main/java/dev/tricht/lunaris/util/platform/windows/VulkanFullscreenFixer.kt create mode 100644 src/main/java/dev/tricht/lunaris/util/platform/windows/WindowFocusListener.kt create mode 100644 src/main/java/dev/tricht/lunaris/util/platform/windows/WindowsKeyboard.kt diff --git a/src/main/java/dev/tricht/lunaris/Lunaris.kt b/src/main/java/dev/tricht/lunaris/Lunaris.kt index c83e2e5..f3d74e4 100644 --- a/src/main/java/dev/tricht/lunaris/Lunaris.kt +++ b/src/main/java/dev/tricht/lunaris/Lunaris.kt @@ -7,20 +7,23 @@ import dev.tricht.lunaris.com.pathofexile.middleware.PseudoModsMiddleware import dev.tricht.lunaris.com.pathofexile.middleware.TradeMiddleware import dev.tricht.lunaris.info.poeprices.PoePricesAPI import dev.tricht.lunaris.item.ItemGrabber -import dev.tricht.lunaris.listeners.* +import dev.tricht.lunaris.listeners.ListenerStack import dev.tricht.lunaris.ninja.poe.PoeNinjaItemResolver import dev.tricht.lunaris.util.ErrorUtil import dev.tricht.lunaris.util.Properties import dev.tricht.lunaris.util.SystemTray +import dev.tricht.lunaris.util.platform.windows.VulkanFullscreenFixer import javafx.application.Platform +import dev.tricht.lunaris.util.Platform as LPlatform import org.jnativehook.GlobalScreen import org.slf4j.LoggerFactory - -import javax.swing.* -import java.awt.* -import java.util.ArrayList +import java.awt.AWTException +import java.awt.Robot +import java.util.* import java.util.logging.Level import java.util.logging.Logger +import javax.swing.UIManager + class Lunaris private constructor() { @@ -94,6 +97,11 @@ class Lunaris private constructor() { pathOfExileAPI?.sessionId = Properties.getProperty(Properties.POESESSID) } + setupVulcanFix() + Properties.addPropertyListener("general.vulcan_fix") { + setupVulcanFix() + } + ListenerStack().startListeners(itemGrabber, robot, pathOfExileAPI, poePricesAPI) // For some reason the JavaFX thread will completely stop after closing @@ -117,4 +125,14 @@ class Lunaris private constructor() { } ItemTransformer.setMiddleware(tradeMiddlewareArrayList) } + + private fun setupVulcanFix() { + if (LPlatform.isWindows) { + if (Properties.getProperty("general.vulcan_fix", "0") == "1") { + VulkanFullscreenFixer.fixFullscreen(); + } else { + VulkanFullscreenFixer.removeHook(); + } + } + } } \ No newline at end of file diff --git a/src/main/java/dev/tricht/lunaris/settings/general/GeneralGUI.java b/src/main/java/dev/tricht/lunaris/settings/general/GeneralGUI.java index 49cf1bf..d25b7eb 100644 --- a/src/main/java/dev/tricht/lunaris/settings/general/GeneralGUI.java +++ b/src/main/java/dev/tricht/lunaris/settings/general/GeneralGUI.java @@ -2,13 +2,17 @@ import dev.tricht.lunaris.com.pathofexile.PathOfExileAPI; import dev.tricht.lunaris.util.Properties; +import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.fxml.Initializable; +import javafx.scene.control.CheckBox; import javafx.scene.control.ChoiceBox; import javafx.scene.control.TextField; import lombok.extern.slf4j.Slf4j; import java.net.URL; +import java.util.HashMap; +import java.util.Map; import java.util.ResourceBundle; @Slf4j @@ -20,6 +24,10 @@ public class GeneralGUI implements Initializable { private TextField poesessid; @FXML private TextField characterName; + @FXML + private CheckBox vulcanFix; + + private HashMap propertyMap; public GeneralGUI(){ @@ -40,5 +48,19 @@ public void initialize(URL url, ResourceBundle resourceBundle) { -> Properties.INSTANCE.writeProperty(Properties.CHARACTER_NAME, t1)); poesessid.textProperty().addListener((observableValue, s, t1) -> Properties.INSTANCE.writeProperty(Properties.POESESSID, t1)); + + propertyMap = new HashMap<>(); + propertyMap.put(vulcanFix, "general.vulcan_fix"); + for (Map.Entry entry :propertyMap.entrySet()) { + entry.getKey().setSelected(Properties.INSTANCE.getProperty(entry.getValue(), "0").equals("1")); + } + } + + public void toggleCheckbox(ActionEvent actionEvent) { + CheckBox source = (CheckBox) actionEvent.getSource(); + if (!propertyMap.containsKey(source)) { + return; + } + Properties.INSTANCE.writeProperty(propertyMap.get(source), source.isSelected() ? "1" : "0"); } } diff --git a/src/main/java/dev/tricht/lunaris/util/platform/windows/VulkanFullscreenFixer.kt b/src/main/java/dev/tricht/lunaris/util/platform/windows/VulkanFullscreenFixer.kt new file mode 100644 index 0000000..f32b94e --- /dev/null +++ b/src/main/java/dev/tricht/lunaris/util/platform/windows/VulkanFullscreenFixer.kt @@ -0,0 +1,74 @@ +package dev.tricht.lunaris.util.platform.windows + +import com.sun.jna.platform.win32.User32 +import java.util.function.Consumer + + +class VulkanFullscreenFixer { + + companion object { + var isPoEActive = false; + lateinit var focusListener: WindowFocusListener; + + fun fixFullscreen() { + val focusConsumer = Consumer { windowTitle: String? -> + if (!windowTitle.equals("Path of Exile")) { + println(windowTitle) + isPoEActive = false; + } else if (windowTitle.equals("Path of Exile") && !isPoEActive) { + isPoEActive = true; + this.changeGameWindowProperties() + } + } + focusListener = WindowFocusListener(focusConsumer) + this.changeGameWindowProperties() + } + + fun changeGameWindowProperties() { + var hWnd = User32.INSTANCE.FindWindow(null, "Path of Exile"); + if (hWnd != null) { + val GWL_STYLE = -16 + val WS_BORDER = 0x00800000 + val WS_DLGFRAME = 0x00400000 + val WS_CAPTION = WS_BORDER or WS_DLGFRAME + + var style = User32.INSTANCE.GetWindowLong(hWnd, GWL_STYLE); + if(style == (style and WS_CAPTION.inv())) { + return; + } + + Thread.sleep(1000); + + User32.INSTANCE.SetWindowLong(hWnd, GWL_STYLE, style and WS_CAPTION.inv()); + + User32.INSTANCE.SetForegroundWindow(hWnd); + + val KEY_LWIN = 0x5BL; + val KEY_UP_ARROW = 0x26L; + val KEY_DOWN_ARROW = 0x28L; + WindowsKeyboard.sendKeyDown(KEY_LWIN); + + WindowsKeyboard.sendKeyDown(KEY_UP_ARROW); + WindowsKeyboard.sendKeyUp(KEY_UP_ARROW); + + Thread.sleep(250); + + WindowsKeyboard.sendKeyDown(KEY_DOWN_ARROW); + WindowsKeyboard.sendKeyUp(KEY_DOWN_ARROW); + + Thread.sleep(250); + + WindowsKeyboard.sendKeyDown(KEY_UP_ARROW); + WindowsKeyboard.sendKeyUp(KEY_UP_ARROW); + + WindowsKeyboard.sendKeyUp(KEY_LWIN); + } + } + + fun removeHook() { + if (this::focusListener.isInitialized) { + focusListener.destroy() + }; + } + } +} \ No newline at end of file diff --git a/src/main/java/dev/tricht/lunaris/util/platform/windows/WindowFocusListener.kt b/src/main/java/dev/tricht/lunaris/util/platform/windows/WindowFocusListener.kt new file mode 100644 index 0000000..fa63f49 --- /dev/null +++ b/src/main/java/dev/tricht/lunaris/util/platform/windows/WindowFocusListener.kt @@ -0,0 +1,64 @@ +package dev.tricht.lunaris.util.platform.windows + +import com.sun.jna.Native +import com.sun.jna.platform.win32.User32 +import com.sun.jna.platform.win32.WinDef.* +import com.sun.jna.platform.win32.WinNT.HANDLE +import com.sun.jna.platform.win32.WinUser.MSG +import com.sun.jna.platform.win32.WinUser.WinEventProc +import java.util.function.Consumer + +class WindowFocusListener(private val callback: Consumer) { + private var winHookThread: Thread? = null + private var winHookRunning = false + private var winHook: HANDLE? = null + + private var EVENT_SYSTEM_FOREGROUND = 0x0003 + private val WINEVENT_SKIPOWNPROCESS = 0x0002 + + private fun initWinHook() { + + val testproc = WinEventProc { _: HANDLE?, _: DWORD?, _: HWND?, _: LONG?, _: LONG?, _: DWORD?, _: DWORD? -> + val buf = CharArray(1024 * 2) + User32.INSTANCE.GetWindowText(User32.INSTANCE.GetForegroundWindow(), buf, 1024) + callback.accept(Native.toString(buf)) + } + winHookThread = Thread(Runnable { + winHook = User32.INSTANCE.SetWinEventHook( + EVENT_SYSTEM_FOREGROUND, + EVENT_SYSTEM_FOREGROUND, + null, testproc, 0, 0, + WINEVENT_SKIPOWNPROCESS) + winHookRunning = true + val msg = MSG() + while (winHookRunning) { + while (User32.INSTANCE.PeekMessage(msg, null, 0, 0, 0)) { + User32.INSTANCE.TranslateMessage(msg) + User32.INSTANCE.DispatchMessage(msg) + } + try { + Thread.sleep(50) + } catch (e: InterruptedException) { + } + } + }, "Lunaris hook thread") + winHookThread!!.priority = Thread.MIN_PRIORITY + winHookThread!!.start() + } + + fun destroy() { + winHookRunning = false + try { + winHookThread!!.join(500) + } catch (ex: InterruptedException) { + System.err.println("joining error: $ex") + } + if (winHook != null) { + User32.INSTANCE.UnhookWinEvent(winHook) + } + } + + init { + initWinHook() + } +} \ No newline at end of file diff --git a/src/main/java/dev/tricht/lunaris/util/platform/windows/WindowsKeyboard.kt b/src/main/java/dev/tricht/lunaris/util/platform/windows/WindowsKeyboard.kt new file mode 100644 index 0000000..560b574 --- /dev/null +++ b/src/main/java/dev/tricht/lunaris/util/platform/windows/WindowsKeyboard.kt @@ -0,0 +1,39 @@ +package dev.tricht.lunaris.util.platform.windows + +import com.sun.jna.platform.win32.BaseTSD.ULONG_PTR +import com.sun.jna.platform.win32.User32 +import com.sun.jna.platform.win32.WinDef.DWORD +import com.sun.jna.platform.win32.WinDef.WORD +import com.sun.jna.platform.win32.WinUser.INPUT + + +class WindowsKeyboard { + companion object { + private val KEY_DOWN = 0L; + private val KEY_UP = 2L; + + fun sendKeyDown(c: Long) { + val input = INPUT() + input.type = DWORD(INPUT.INPUT_KEYBOARD.toLong()) + input.input.setType("ki") + input.input.ki.wScan = WORD(0) + input.input.ki.time = DWORD(0) + input.input.ki.dwExtraInfo = ULONG_PTR(0) + input.input.ki.wVk = WORD(c) + input.input.ki.dwFlags = DWORD(KEY_DOWN) + User32.INSTANCE.SendInput(DWORD(1), input.toArray(1) as Array, input.size()) + } + + fun sendKeyUp(c: Long) { + val input = INPUT() + input.type = DWORD(INPUT.INPUT_KEYBOARD.toLong()) + input.input.setType("ki") + input.input.ki.wScan = WORD(0) + input.input.ki.time = DWORD(0) + input.input.ki.dwExtraInfo = ULONG_PTR(0) + input.input.ki.wVk = WORD(c) + input.input.ki.dwFlags = DWORD(KEY_UP) + User32.INSTANCE.SendInput(DWORD(1), input.toArray(1) as Array, input.size()) + } + } +} \ No newline at end of file diff --git a/src/main/resources/settings/general/general.fxml b/src/main/resources/settings/general/general.fxml index 25a5f9c..0f2bd9d 100644 --- a/src/main/resources/settings/general/general.fxml +++ b/src/main/resources/settings/general/general.fxml @@ -29,6 +29,7 @@ + From f45d7c3b6dc152e678d8e9869f8a2b633da2d395 Mon Sep 17 00:00:00 2001 From: Peter Vaassens Date: Thu, 11 Jun 2020 02:02:41 +0200 Subject: [PATCH 2/2] Add vulcan info to README --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 456d9bf..96c0674 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,12 @@ Having trouble? [Open an issue](https://github.com/mtricht/lunaris/issues/new). Linux users, see this [page](https://github.com/mtricht/lunaris/blob/master/LINUX.md). +## FAQ +### Lunaris is not working with the Vulkan renderer +First, change your display mode to windowed (no worries, you can still play fullscreen). +Then in the Lunaris options menu, tick "Vulcan fix". You should now be able to enjoy the features of Lunaris while playing fullscreen PoE. + + ## Boss screenshots Are we missing a boss? You can help by making a screenshot of the boss in the maps you’re already running anyway, and filling it out in this form: https://forms.gle/tE9e6PshZ1QWutV48 We will make sure to credit everyone that has submitted a screenshot somewhere in the tool! Thanks in advance!