From 86b79ad90acb257c19b6551a7be9f13b3b21e0f3 Mon Sep 17 00:00:00 2001 From: chsami <23292806+chsami@users.noreply.github.com> Date: Thu, 15 Oct 2026 12:32:40 +0200 Subject: [PATCH] fix(playermonitor): create click log dir before saving on stop (1.0.5) saveMouseClicks wrote to ~/.runelite/PlayerMonitor/click_count.log without creating the directory, which is only created by loadMouseClicks and is skipped in lite mode. Stopping the plugin then threw FileNotFoundException and aborted shutDown before the listener and script were cleaned up. Create the parent directory before writing, close the writer with try-with-resources, and catch the IOException in shutDown so cleanup runs. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01LjtEMzQHGuq4M1Mpqk9pPV --- .../playermonitor/PlayerMonitorPlugin.java | 29 +++++++------- .../PlayerMonitorPluginTest.java | 39 +++++++++++++++++++ 2 files changed, 55 insertions(+), 13 deletions(-) create mode 100644 src/test/java/net/runelite/client/plugins/microbot/playermonitor/PlayerMonitorPluginTest.java diff --git a/src/main/java/net/runelite/client/plugins/microbot/playermonitor/PlayerMonitorPlugin.java b/src/main/java/net/runelite/client/plugins/microbot/playermonitor/PlayerMonitorPlugin.java index a433ff89a5..ec63f46ddc 100644 --- a/src/main/java/net/runelite/client/plugins/microbot/playermonitor/PlayerMonitorPlugin.java +++ b/src/main/java/net/runelite/client/plugins/microbot/playermonitor/PlayerMonitorPlugin.java @@ -37,7 +37,7 @@ import java.util.stream.Collectors; @PluginDescriptor( - version = "1.0.4", + version = "1.0.5", name = PluginDescriptor.eXioStorm + "Player Monitor", enabledByDefault = false, minClientVersion = "2.0.0", @@ -215,7 +215,11 @@ protected void shutDown() throws Exception { if (this.flashOverlay != null) { overlayManager.remove(flashOverlay); } - saveMouseClicks(); + try { + saveMouseClicks(); + } catch (IOException e) { + log.warn("Failed to save mouse clicks", e); + } this.mouseManager.unregisterMouseListener((net.runelite.client.input.MouseListener)this.mouseListener); this.mouseListener = null; if (this.overlayOn) { @@ -275,17 +279,16 @@ public static void resetMouseClickCounterListener() { } } public static void saveMouseClicks() throws IOException { - if (!CLICK_TOTAL_FILE.exists()) - try { - if (!CLICK_TOTAL_FILE.createNewFile()) - System.out.println("Failed to create log file"); - } catch (IOException e) { - e.printStackTrace(); - } - FileWriter writer = new FileWriter(CLICK_TOTAL_FILE); - Integer[] totals = { Integer.valueOf(getLeftClickCounter()) }; - writer.write("" + totals[FILE_CLICK_TYPE_INDICES.LEFT.getValue()] + " "); - writer.close(); + writeClickCount(CLICK_TOTAL_FILE, getLeftClickCounter()); + } + static void writeClickCount(File file, int leftClicks) throws IOException { + File dir = file.getParentFile(); + if (dir != null && !dir.isDirectory() && !dir.mkdirs() && !dir.isDirectory()) + throw new IOException("Failed to create directory " + dir); + Integer[] totals = { Integer.valueOf(leftClicks) }; + try (FileWriter writer = new FileWriter(file)) { + writer.write("" + totals[FILE_CLICK_TYPE_INDICES.LEFT.getValue()] + " "); + } } public void loadMouseClicks() throws FileNotFoundException { if (!this.CLICK_TOTAL_DIR.mkdir() && CLICK_TOTAL_FILE.exists()) { diff --git a/src/test/java/net/runelite/client/plugins/microbot/playermonitor/PlayerMonitorPluginTest.java b/src/test/java/net/runelite/client/plugins/microbot/playermonitor/PlayerMonitorPluginTest.java new file mode 100644 index 0000000000..e29ce1c7f2 --- /dev/null +++ b/src/test/java/net/runelite/client/plugins/microbot/playermonitor/PlayerMonitorPluginTest.java @@ -0,0 +1,39 @@ +package net.runelite.client.plugins.microbot.playermonitor; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class PlayerMonitorPluginTest { + + @TempDir + Path tempDir; + + @Test + void writeClickCountCreatesMissingDirectory() throws IOException { + File file = tempDir.resolve("PlayerMonitor").resolve("click_count.log").toFile(); + + PlayerMonitorPlugin.writeClickCount(file, 42); + + assertTrue(file.isFile()); + assertEquals("42 ", new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8)); + } + + @Test + void writeClickCountOverwritesExistingFile() throws IOException { + File file = tempDir.resolve("click_count.log").toFile(); + Files.write(file.toPath(), "999 ".getBytes(StandardCharsets.UTF_8)); + + PlayerMonitorPlugin.writeClickCount(file, 7); + + assertEquals("7 ", new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8)); + } +}