From d416a638a19f15e19d097d7414eeb3347d6e6a0b Mon Sep 17 00:00:00 2001 From: Drefvelin <54400154+Drefvelin@users.noreply.github.com> Date: Thu, 24 Sep 2026 20:45:22 +0000 Subject: [PATCH] Let staff skip the Survival Discord link requirement. --- .../tfmcweb/gate/DiscordGateService.java | 14 +++++++++++++- src/main/resources/plugin.yml | 3 +++ .../tfmcweb/gate/DiscordGateServiceTest.java | 13 +++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/tfminecraft/tfmcweb/gate/DiscordGateService.java b/src/main/java/net/tfminecraft/tfmcweb/gate/DiscordGateService.java index c2487bd..7b84559 100644 --- a/src/main/java/net/tfminecraft/tfmcweb/gate/DiscordGateService.java +++ b/src/main/java/net/tfminecraft/tfmcweb/gate/DiscordGateService.java @@ -16,9 +16,13 @@ /** * Applies Survival Discord gate via RPCharacters (optional, reflection). + * Players with {@link #BYPASS_PERMISSION} are not gated. */ public final class DiscordGateService { + /** Survival play without a Discord link. Registered in plugin.yml. */ + public static final String BYPASS_PERMISSION = "tfmcweb.discord.bypass"; + private final JavaPlugin plugin; private final LinkCache linkCache; private Plugin resolvedRpc; @@ -90,10 +94,18 @@ public void applyGate(Player player, boolean eligible) { if (player == null || !isRpcAvailable()) { return; } - boolean required = player.getGameMode() == GameMode.SURVIVAL && !eligible; + boolean required = requiresGate( + player.getGameMode(), + eligible, + player.hasPermission(BYPASS_PERMISSION) + ); invokeGate(player.getUniqueId(), player, required); } + static boolean requiresGate(GameMode mode, boolean eligible, boolean bypass) { + return mode == GameMode.SURVIVAL && !eligible && !bypass; + } + /** Offline-safe: set UUID gate flag; RPC reevaluates if online. */ public void applyGate(UUID uuid, boolean eligible) { if (uuid == null || !isRpcAvailable()) { diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index f219234..0d527e6 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -37,6 +37,9 @@ permissions: tfmcweb.linkdiscord: description: Use /linkdiscord and /unlinkdiscord default: true + tfmcweb.discord.bypass: + description: Play Survival without linking Discord + default: false tfmcweb.admin: description: Admin /web commands default: op diff --git a/src/test/java/net/tfminecraft/tfmcweb/gate/DiscordGateServiceTest.java b/src/test/java/net/tfminecraft/tfmcweb/gate/DiscordGateServiceTest.java index 2d8ff73..bb30502 100644 --- a/src/test/java/net/tfminecraft/tfmcweb/gate/DiscordGateServiceTest.java +++ b/src/test/java/net/tfminecraft/tfmcweb/gate/DiscordGateServiceTest.java @@ -73,6 +73,19 @@ void freezesUnlinkedSurvivalPlayerAfterRpcEnablesLater() { assertTrue(gate.isRpcAvailable()); } + @Test + void staffBypassSkipsSurvivalGateWhenUnlinked() { + when(rpc.isEnabled()).thenReturn(true); + when(player.hasPermission(DiscordGateService.BYPASS_PERMISSION)).thenReturn(true); + cache.putUnlinked(uuid); + + gate.applyGate(player); + + assertEquals(Boolean.FALSE, RpcPlugin.lastRequired); + assertFalse(DiscordGateService.requiresGate(GameMode.SURVIVAL, false, true)); + assertTrue(DiscordGateService.requiresGate(GameMode.SURVIVAL, false, false)); + } + @Test void releasesEligiblePlayersAndDoesNotFreezeOtherGameModes() { when(rpc.isEnabled()).thenReturn(true);