From bdfd297cb752e1fce1609e5a00148634ee82b668 Mon Sep 17 00:00:00 2001 From: Good627 <193092356+Good627@users.noreply.github.com> Date: Mon, 2 Nov 2026 19:52:04 +0200 Subject: [PATCH] feat(bridge): add 3-state Login/logout messages mode --- src/tel/eden/mod/EdenModClient.java | 8 +++- src/tel/eden/mod/config/BridgeConfig.java | 47 +++++++++++++++---- src/tel/eden/mod/gui/BridgeConfigScreen.java | 8 +++- .../tel/eden/mod/config/BridgeConfigTest.java | 40 ++++++++++++++++ 4 files changed, 92 insertions(+), 11 deletions(-) create mode 100644 test/tel/eden/mod/config/BridgeConfigTest.java diff --git a/src/tel/eden/mod/EdenModClient.java b/src/tel/eden/mod/EdenModClient.java index 13181d8..97dc9e6 100644 --- a/src/tel/eden/mod/EdenModClient.java +++ b/src/tel/eden/mod/EdenModClient.java @@ -1023,11 +1023,17 @@ public void onDiscordMessage(String author, String content, String replyTo, Stri @Override public void onLoginNotice(String username, String color) { + if (config.loginLogoutMode == BridgeConfig.LoginLogoutMode.HIDE_ALL) { + return; + } displayColored(color, () -> DiscordChatFormatter.loginNotice(username)); } @Override public void onLogoutNotice(String username, String color) { + if (config.loginLogoutMode == BridgeConfig.LoginLogoutMode.HIDE_ALL) { + return; + } displayColored(color, () -> DiscordChatFormatter.logoutNotice(username)); } @@ -2718,7 +2724,7 @@ private void onBridgeConnected() { // backend pairs the logout to this, so skipping it keeps both quiet. // Presence is always sent — it drives the online/dormant state, not a // chat notice. - if (config.announceSelfPresence) { + if (config.loginLogoutMode == BridgeConfig.LoginLogoutMode.ALL) { current.sendLogin(); } current.sendPresence(inGameWorld); // send whatever state we already detected diff --git a/src/tel/eden/mod/config/BridgeConfig.java b/src/tel/eden/mod/config/BridgeConfig.java index fcc0078..6bd372c 100644 --- a/src/tel/eden/mod/config/BridgeConfig.java +++ b/src/tel/eden/mod/config/BridgeConfig.java @@ -47,13 +47,31 @@ private static Path resolveConfigPath() { /** Whether the bridge should connect while on Wynncraft. */ public boolean enabled = true; + public enum LoginLogoutMode { + ALL("All"), HIDE_MINE("Hide Mine"), HIDE_ALL("Hide All"); + + private final String label; + + LoginLogoutMode(String label) { + this.label = label; + } + + public String label() { + return label; + } + } + + /** Legacy toggle kept only to migrate older configs into {@link #loginLogoutMode}. */ + @Deprecated + public Boolean announceSelfPresence = null; + /** - * Whether your own login/logout is announced to the guild bridge (both in-game - * and in the Discord bridge chat). On by default; turn it off to keep your own - * comings and goings quiet. Other members' presence notices are unaffected, and - * you still appear in {@code /eden online} either way. + * Visibility of login/logout and streak notices: + * ALL: broadcast own login/logout and streaks, and display others'. + * HIDE_MINE: keep own login/logout and streaks quiet, and display others'. + * HIDE_ALL: keep own login/logout and streaks quiet, and hide others'. */ - public boolean announceSelfPresence = true; + public LoginLogoutMode loginLogoutMode = LoginLogoutMode.ALL; /** Play a short chime when Eden mail arrives. On by default. */ public boolean mailSound = true; @@ -421,6 +439,20 @@ public CommandKeybind(String input, String command) { } } + static void migrateLegacyFields(BridgeConfig config) { + if (config.showGameMessages != null) { + config.gameDisplayMode = config.showGameMessages ? GameDisplayMode.ALL : GameDisplayMode.NONE; + config.showGameMessages = null; + } + if (config.announceSelfPresence != null) { + config.loginLogoutMode = config.announceSelfPresence ? LoginLogoutMode.ALL : LoginLogoutMode.HIDE_MINE; + config.announceSelfPresence = null; + } + if (config.loginLogoutMode == null) { + config.loginLogoutMode = LoginLogoutMode.ALL; + } + } + /** Load the config from disk, or return defaults (and write them) if absent. */ public static BridgeConfig load() { if (Files.isRegularFile(PATH)) { @@ -428,10 +460,7 @@ public static BridgeConfig load() { String json = Files.readString(PATH, StandardCharsets.UTF_8); BridgeConfig config = GSON.fromJson(json, BridgeConfig.class); if (config != null) { - if (config.showGameMessages != null) { - config.gameDisplayMode = config.showGameMessages ? GameDisplayMode.ALL : GameDisplayMode.NONE; - config.showGameMessages = null; - } + migrateLegacyFields(config); if (config.commandAliases == null) { config.commandAliases = new ArrayList<>(); } diff --git a/src/tel/eden/mod/gui/BridgeConfigScreen.java b/src/tel/eden/mod/gui/BridgeConfigScreen.java index 527d081..fd40e1a 100644 --- a/src/tel/eden/mod/gui/BridgeConfigScreen.java +++ b/src/tel/eden/mod/gui/BridgeConfigScreen.java @@ -115,7 +115,7 @@ protected void init() { // --- One line per setting; the list handles layout + smooth scrolling. --- // General addToggleRow(Category.GENERAL, "Bridge", () -> config.enabled, v -> config.enabled = v, "Enabled", "Disabled", true); - addToggleRow(Category.GENERAL, "My login/logout messages", () -> config.announceSelfPresence, v -> config.announceSelfPresence = v, "On", "Off", true); + addCycleRow(Category.GENERAL, "Login/logout messages", () -> config.loginLogoutMode.label(), () -> config.loginLogoutMode = nextLoginLogoutMode(config.loginLogoutMode), () -> config.loginLogoutMode = BridgeConfig.LoginLogoutMode.ALL); addToggleRow(Category.GENERAL, "Mail sound", () -> config.mailSound, v -> config.mailSound = v, "On", "Off", true); addToggleRow(Category.GENERAL, "Party feed", () -> config.partyAnnounce, v -> config.partyAnnounce = v, "On", "Off", true); addToggleRow(Category.GENERAL, "Auto /stream on join", () -> config.autoStream, v -> config.autoStream = v, "On", "Off", false); @@ -283,6 +283,12 @@ private void startLinkFlow() { mod.startLinkFlow(() -> this.minecraft.execute(() -> this.minecraft.setScreen(BridgeConfigScreen.create(parent, mod)))); } + private BridgeConfig.LoginLogoutMode nextLoginLogoutMode(BridgeConfig.LoginLogoutMode current) { + BridgeConfig.LoginLogoutMode safe = current != null ? current : BridgeConfig.LoginLogoutMode.ALL; + BridgeConfig.LoginLogoutMode[] values = BridgeConfig.LoginLogoutMode.values(); + return values[(safe.ordinal() + 1) % values.length]; + } + private BridgeConfig.GameDisplayMode nextGameMode(BridgeConfig.GameDisplayMode current) { BridgeConfig.GameDisplayMode[] values = BridgeConfig.GameDisplayMode.values(); return values[(current.ordinal() + 1) % values.length]; diff --git a/test/tel/eden/mod/config/BridgeConfigTest.java b/test/tel/eden/mod/config/BridgeConfigTest.java new file mode 100644 index 0000000..544ce9d --- /dev/null +++ b/test/tel/eden/mod/config/BridgeConfigTest.java @@ -0,0 +1,40 @@ +package tel.eden.mod.config; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.google.gson.Gson; +import org.junit.jupiter.api.Test; + +class BridgeConfigTest { + @Test + void defaultsLoginLogoutModeToAll() { + BridgeConfig config = new BridgeConfig(); + assertEquals(BridgeConfig.LoginLogoutMode.ALL, config.loginLogoutMode); + } + + @Test + void preservesLoginLogoutModeAcrossSerialization() { + Gson gson = new Gson(); + BridgeConfig config = new BridgeConfig(); + config.loginLogoutMode = BridgeConfig.LoginLogoutMode.HIDE_ALL; + + String json = gson.toJson(config); + BridgeConfig loaded = gson.fromJson(json, BridgeConfig.class); + + assertEquals(BridgeConfig.LoginLogoutMode.HIDE_ALL, loaded.loginLogoutMode); + } + + @Test + void migratesLegacyAnnounceSelfPresenceWhenPresent() { + Gson gson = new Gson(); + String falseJson = "{\"announceSelfPresence\":false}"; + BridgeConfig loadedFalse = gson.fromJson(falseJson, BridgeConfig.class); + BridgeConfig.migrateLegacyFields(loadedFalse); + assertEquals(BridgeConfig.LoginLogoutMode.HIDE_MINE, loadedFalse.loginLogoutMode); + + String trueJson = "{\"announceSelfPresence\":true}"; + BridgeConfig loadedTrue = gson.fromJson(trueJson, BridgeConfig.class); + BridgeConfig.migrateLegacyFields(loadedTrue); + assertEquals(BridgeConfig.LoginLogoutMode.ALL, loadedTrue.loginLogoutMode); + } +}