From 6e154a457d2b12fd8d0205cbde0ad3af46f4c6ed Mon Sep 17 00:00:00 2001 From: Ilyas Date: Wed, 25 Jun 2025 13:54:15 +0200 Subject: [PATCH 1/6] Implement Geyser plugin detection and Bedrock tunnel creation in PlayitBukkit, PlayitKeysSetup, and PlayitManager classes --- .../gg/playit/minecraft/PlayitBukkit.java | 44 +++++++++++++++- .../gg/playit/minecraft/PlayitKeysSetup.java | 50 +++++++++++++++---- .../gg/playit/minecraft/PlayitManager.java | 8 ++- 3 files changed, 88 insertions(+), 14 deletions(-) diff --git a/src/main/java/gg/playit/minecraft/PlayitBukkit.java b/src/main/java/gg/playit/minecraft/PlayitBukkit.java index e9757f4..9faa16e 100644 --- a/src/main/java/gg/playit/minecraft/PlayitBukkit.java +++ b/src/main/java/gg/playit/minecraft/PlayitBukkit.java @@ -14,6 +14,11 @@ import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.plugin.Plugin; +import org.yaml.snakeyaml.Yaml; +import java.io.File; +import java.io.FileInputStream; +import java.util.Map; import java.io.IOException; import java.util.List; @@ -31,10 +36,46 @@ public final class PlayitBukkit extends JavaPlugin implements Listener { Server server; + private boolean isGeyserPresent = false; + private int geyserPort = 19132; + @Override public void onEnable() { server = Bukkit.getServer(); + // Detect Geyser plugin + PluginManager pm = Bukkit.getServer().getPluginManager(); + Plugin geyser = pm.getPlugin("Geyser-Spigot"); + if (geyser != null && geyser.isEnabled()) { + isGeyserPresent = true; + // Try to read the port from Geyser config + try { + File geyserConfig = new File("plugins/Geyser-Spigot/config.yml"); + if (geyserConfig.exists()) { + Yaml yaml = new Yaml(); + try (FileInputStream fis = new FileInputStream(geyserConfig)) { + Map config = yaml.load(fis); + if (config != null && config.containsKey("bedrock")) { + Object bedrockSection = config.get("bedrock"); + if (bedrockSection instanceof Map) { + Object portObj = ((Map) bedrockSection).get("port"); + if (portObj instanceof Number) { + geyserPort = ((Number) portObj).intValue(); + } else if (portObj instanceof String) { + try { + geyserPort = Integer.parseInt((String) portObj); + } catch (NumberFormatException ignore) {} + } + } + } + } + } + } catch (Exception e) { + log.warning("Failed to read Geyser config: " + e.getMessage()); + } + log.info("Geyser detected, Bedrock port: " + geyserPort); + } + var command = getCommand("playit"); if (command != null) { command.setExecutor(this); @@ -50,7 +91,6 @@ public void onEnable() { resetConnection(secretKey); try { - PluginManager pm = Bukkit.getServer().getPluginManager(); pm.registerEvents(this, this); } catch (Exception e) { } @@ -261,7 +301,7 @@ private void resetConnection(String secretKey) { playitManager.shutdown(); } - playitManager = new PlayitManager(this); + playitManager = new PlayitManager(this, isGeyserPresent, geyserPort); try { int waitSeconds = getConfig().getInt(CFG_CONNECTION_TIMEOUT_SECONDS); if (waitSeconds != 0) { diff --git a/src/main/java/gg/playit/minecraft/PlayitKeysSetup.java b/src/main/java/gg/playit/minecraft/PlayitKeysSetup.java index 7bf5eec..832b75d 100644 --- a/src/main/java/gg/playit/minecraft/PlayitKeysSetup.java +++ b/src/main/java/gg/playit/minecraft/PlayitKeysSetup.java @@ -25,10 +25,14 @@ public class PlayitKeysSetup { public static final int STATE_ERROR = 5; public static final int STATE_SHUTDOWN = 0; private final ApiClient openClient = new ApiClient(null); + private final boolean isGeyserPresent; + private final int geyserPort; - public PlayitKeysSetup(String secretKey, AtomicInteger state) { + public PlayitKeysSetup(String secretKey, AtomicInteger state, boolean isGeyserPresent, int geyserPort) { keys.secretKey = secretKey; this.state = state; + this.isGeyserPresent = isGeyserPresent; + this.geyserPort = geyserPort; } private final PlayitKeys keys = new PlayitKeys(); @@ -117,20 +121,46 @@ public PlayitKeys progress() throws IOException { if (tunnel.tunnelType == TunnelType.MinecraftJava) { keys.tunnelAddress = tunnel.displayAddress; log.info("found minecraft java tunnel: " + keys.tunnelAddress); - return keys; + // Don't return yet, check for Bedrock tunnel if Geyser is present } } - log.info("create new minecraft java tunnel"); + // Always create Java tunnel if not found + if (keys.tunnelAddress == null) { + log.info("create new minecraft java tunnel"); - var create = new CreateTunnel(); - create.localIp = "127.0.0.1"; - create.portCount = 1; - create.portType = PortType.TCP; - create.tunnelType = TunnelType.MinecraftJava; - create.agentId = keys.agentId; + var create = new CreateTunnel(); + create.localIp = "127.0.0.1"; + create.portCount = 1; + create.portType = PortType.TCP; + create.tunnelType = TunnelType.MinecraftJava; + create.agentId = keys.agentId; - api.createTunnel(create); + api.createTunnel(create); + } + + // If Geyser is present, ensure a Bedrock UDP tunnel exists + if (isGeyserPresent) { + boolean foundBedrock = false; + for (AccountTunnel tunnel : tunnels.tunnels) { + if (tunnel.tunnelType == TunnelType.MinecraftBedrock) { + foundBedrock = true; + log.info("found minecraft bedrock tunnel: " + tunnel.displayAddress); + break; + } + } + if (!foundBedrock) { + log.info("create new minecraft bedrock UDP tunnel on port " + geyserPort); + var create = new CreateTunnel(); + create.localIp = "127.0.0.1"; + create.localPort = geyserPort; + create.portCount = 1; + create.portType = PortType.UDP; + create.tunnelType = TunnelType.MinecraftBedrock; + create.agentId = keys.agentId; + api.createTunnel(create); + } + } return null; } diff --git a/src/main/java/gg/playit/minecraft/PlayitManager.java b/src/main/java/gg/playit/minecraft/PlayitManager.java index fa30346..fb58dab 100644 --- a/src/main/java/gg/playit/minecraft/PlayitManager.java +++ b/src/main/java/gg/playit/minecraft/PlayitManager.java @@ -19,16 +19,20 @@ public class PlayitManager implements Runnable { private final PlayitConnectionTracker tracker = new PlayitConnectionTracker(); private final PlayitBukkit plugin; + private final boolean isGeyserPresent; + private final int geyserPort; - public PlayitManager(PlayitBukkit plugin) { + public PlayitManager(PlayitBukkit plugin, boolean isGeyserPresent, int geyserPort) { this.plugin = plugin; + this.isGeyserPresent = isGeyserPresent; + this.geyserPort = geyserPort; var secret = plugin.getConfig().getString(PlayitBukkit.CFG_AGENT_SECRET_KEY); if (secret != null && secret.length() < 32) { secret = null; } - setup = new PlayitKeysSetup(secret, state); + setup = new PlayitKeysSetup(secret, state, isGeyserPresent, geyserPort); } private final PlayitKeysSetup setup; From ea2e7ed7f6f2de1079ebd5baea2c89b612370432 Mon Sep 17 00:00:00 2001 From: Ilyas Date: Wed, 25 Jun 2025 13:56:11 +0200 Subject: [PATCH 2/6] Update manual-build.yml --- .github/workflows/manual-build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/manual-build.yml b/.github/workflows/manual-build.yml index e1bb543..af321e6 100644 --- a/.github/workflows/manual-build.yml +++ b/.github/workflows/manual-build.yml @@ -16,7 +16,7 @@ jobs: - name: Build Package run: mvn --batch-mode package - name: Upload jar - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: playit-minecraft-plugin.jar - path: ./target/playit-minecraft-plugin.jar \ No newline at end of file + path: ./target/playit-minecraft-plugin.jar From 0b720548fca0d28f43358329d283197e9bdd898c Mon Sep 17 00:00:00 2001 From: Ilyas Date: Wed, 25 Jun 2025 14:08:00 +0200 Subject: [PATCH 3/6] Refactor tunnel creation logic in PlayitKeysSetup to improve handling of Minecraft Java and Bedrock tunnels. Introduced flags to track tunnel presence and streamlined the creation process for missing tunnels. --- .../gg/playit/minecraft/PlayitKeysSetup.java | 48 ++++++++++--------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/src/main/java/gg/playit/minecraft/PlayitKeysSetup.java b/src/main/java/gg/playit/minecraft/PlayitKeysSetup.java index 832b75d..92b98ca 100644 --- a/src/main/java/gg/playit/minecraft/PlayitKeysSetup.java +++ b/src/main/java/gg/playit/minecraft/PlayitKeysSetup.java @@ -117,16 +117,23 @@ public PlayitKeys progress() throws IOException { var tunnels = api.listTunnels(); keys.tunnelAddress = null; + boolean haveJava = false; + boolean haveBedrock = !isGeyserPresent; + for (AccountTunnel tunnel : tunnels.tunnels) { if (tunnel.tunnelType == TunnelType.MinecraftJava) { keys.tunnelAddress = tunnel.displayAddress; + haveJava = true; log.info("found minecraft java tunnel: " + keys.tunnelAddress); - // Don't return yet, check for Bedrock tunnel if Geyser is present + } + if (isGeyserPresent && tunnel.tunnelType == TunnelType.MinecraftBedrock) { + haveBedrock = true; + log.info("found minecraft bedrock tunnel: " + tunnel.displayAddress); } } // Always create Java tunnel if not found - if (keys.tunnelAddress == null) { + if (!haveJava) { log.info("create new minecraft java tunnel"); var create = new CreateTunnel(); @@ -137,29 +144,26 @@ public PlayitKeys progress() throws IOException { create.agentId = keys.agentId; api.createTunnel(create); + return null; // Wait for tunnel to appear } // If Geyser is present, ensure a Bedrock UDP tunnel exists - if (isGeyserPresent) { - boolean foundBedrock = false; - for (AccountTunnel tunnel : tunnels.tunnels) { - if (tunnel.tunnelType == TunnelType.MinecraftBedrock) { - foundBedrock = true; - log.info("found minecraft bedrock tunnel: " + tunnel.displayAddress); - break; - } - } - if (!foundBedrock) { - log.info("create new minecraft bedrock UDP tunnel on port " + geyserPort); - var create = new CreateTunnel(); - create.localIp = "127.0.0.1"; - create.localPort = geyserPort; - create.portCount = 1; - create.portType = PortType.UDP; - create.tunnelType = TunnelType.MinecraftBedrock; - create.agentId = keys.agentId; - api.createTunnel(create); - } + if (isGeyserPresent && !haveBedrock) { + log.info("create new minecraft bedrock UDP tunnel on port " + geyserPort); + var create = new CreateTunnel(); + create.localIp = "127.0.0.1"; + create.localPort = geyserPort; + create.portCount = 1; + create.portType = PortType.UDP; + create.tunnelType = TunnelType.MinecraftBedrock; + create.agentId = keys.agentId; + api.createTunnel(create); + return null; // Wait for tunnel to appear + } + + // If we have both required tunnels, setup is done + if (haveJava && haveBedrock) { + return keys; } return null; From 2e25c6553cbd7fbf0bd4075af74c9c88262c2050 Mon Sep 17 00:00:00 2001 From: Ilyas Date: Wed, 25 Jun 2025 14:20:17 +0200 Subject: [PATCH 4/6] Enhance logging and error handling during Bedrock tunnel creation in PlayitKeysSetup. Added detailed log statements for tunnel parameters and improved exception handling to capture failures in tunnel creation. --- .../gg/playit/minecraft/PlayitKeysSetup.java | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/main/java/gg/playit/minecraft/PlayitKeysSetup.java b/src/main/java/gg/playit/minecraft/PlayitKeysSetup.java index 92b98ca..f961cb9 100644 --- a/src/main/java/gg/playit/minecraft/PlayitKeysSetup.java +++ b/src/main/java/gg/playit/minecraft/PlayitKeysSetup.java @@ -149,7 +149,7 @@ public PlayitKeys progress() throws IOException { // If Geyser is present, ensure a Bedrock UDP tunnel exists if (isGeyserPresent && !haveBedrock) { - log.info("create new minecraft bedrock UDP tunnel on port " + geyserPort); + log.info("Preparing to create new minecraft bedrock UDP tunnel:"); var create = new CreateTunnel(); create.localIp = "127.0.0.1"; create.localPort = geyserPort; @@ -157,7 +157,19 @@ public PlayitKeys progress() throws IOException { create.portType = PortType.UDP; create.tunnelType = TunnelType.MinecraftBedrock; create.agentId = keys.agentId; - api.createTunnel(create); + log.info(" localIp: " + create.localIp); + log.info(" localPort: " + create.localPort); + log.info(" portCount: " + create.portCount); + log.info(" portType: " + create.portType); + log.info(" tunnelType: " + create.tunnelType); + log.info(" agentId: " + create.agentId); + try { + api.createTunnel(create); + log.info("Successfully requested Bedrock tunnel creation"); + } catch (Exception e) { + log.severe("Failed to create Bedrock tunnel: " + e.getMessage()); + e.printStackTrace(); + } return null; // Wait for tunnel to appear } From 3541cf501f95504f62d42ad4eb57e4b359b14e7f Mon Sep 17 00:00:00 2001 From: Ilyas Date: Wed, 25 Jun 2025 14:24:29 +0200 Subject: [PATCH 5/6] Add soft dependency on Geyser-Spigot in plugin.yml for enhanced compatibility --- src/main/resources/plugin.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 5a3018b..58714c1 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -4,6 +4,7 @@ main: gg.playit.minecraft.PlayitBukkit author: https://playit.gg description: Makes your server public so friends can connect api-version: 1.18 +softdepend: [Geyser-Spigot] commands: playit: From 1b6cb279898f5b5f1dfe4769427245b8feded046 Mon Sep 17 00:00:00 2001 From: Ilyas Date: Wed, 25 Jun 2025 14:37:23 +0200 Subject: [PATCH 6/6] Update PlayitKeysSetup.java remove extra logging --- .../gg/playit/minecraft/PlayitKeysSetup.java | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/src/main/java/gg/playit/minecraft/PlayitKeysSetup.java b/src/main/java/gg/playit/minecraft/PlayitKeysSetup.java index f961cb9..92b98ca 100644 --- a/src/main/java/gg/playit/minecraft/PlayitKeysSetup.java +++ b/src/main/java/gg/playit/minecraft/PlayitKeysSetup.java @@ -149,7 +149,7 @@ public PlayitKeys progress() throws IOException { // If Geyser is present, ensure a Bedrock UDP tunnel exists if (isGeyserPresent && !haveBedrock) { - log.info("Preparing to create new minecraft bedrock UDP tunnel:"); + log.info("create new minecraft bedrock UDP tunnel on port " + geyserPort); var create = new CreateTunnel(); create.localIp = "127.0.0.1"; create.localPort = geyserPort; @@ -157,19 +157,7 @@ public PlayitKeys progress() throws IOException { create.portType = PortType.UDP; create.tunnelType = TunnelType.MinecraftBedrock; create.agentId = keys.agentId; - log.info(" localIp: " + create.localIp); - log.info(" localPort: " + create.localPort); - log.info(" portCount: " + create.portCount); - log.info(" portType: " + create.portType); - log.info(" tunnelType: " + create.tunnelType); - log.info(" agentId: " + create.agentId); - try { - api.createTunnel(create); - log.info("Successfully requested Bedrock tunnel creation"); - } catch (Exception e) { - log.severe("Failed to create Bedrock tunnel: " + e.getMessage()); - e.printStackTrace(); - } + api.createTunnel(create); return null; // Wait for tunnel to appear }