From 5afab3779d10698de0f4feb0d8e45f6d1c6e2917 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Mar 2026 19:26:25 +0000 Subject: [PATCH 1/3] Initial plan From 0541bfde4f6523ccaa11f8d8b494899a330ccaa4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Mar 2026 19:30:01 +0000 Subject: [PATCH 2/3] fix: improve windows compatibility and launcher path handling Co-authored-by: TheCodingSoldier <257933801+TheCodingSoldier@users.noreply.github.com> --- README.md | 2 +- build.gradle | 2 +- .../exceptions/LauncherFailiure.java | 8 +++ .../opengameband/launcher/BasicLauncher.java | 49 ++++++++++++++----- .../org/opengameband/util/DownloadURLs.java | 6 +-- .../org/opengameband/util/MountPoint.java | 11 ++++- 6 files changed, 61 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index ec4c08d..82b327b 100644 --- a/README.md +++ b/README.md @@ -3,5 +3,5 @@ Replacement for the Gameband Launcher This project is an open source replacement of the Gameband + Minecraft launcher. # Status -So far it can launch the minecraft launcher on macOS. +So far it can launch the Minecraft launcher on macOS and Windows. At some point a PixelForge replacement will be implemented, though this requires some reverse engineering effort. diff --git a/build.gradle b/build.gradle index f8cba36..380c69d 100644 --- a/build.gradle +++ b/build.gradle @@ -60,7 +60,7 @@ publishing { } task nativePackage(type: PackageTask, dependsOn: build) { - mainClass = 'org.opengameband.OpenGameband' + mainClass = 'org.opengameband.Main' bundleJre = true generateInstaller = false administratorRequired = false diff --git a/src/main/java/org/opengameband/exceptions/LauncherFailiure.java b/src/main/java/org/opengameband/exceptions/LauncherFailiure.java index 0ec5a39..bf4cffb 100644 --- a/src/main/java/org/opengameband/exceptions/LauncherFailiure.java +++ b/src/main/java/org/opengameband/exceptions/LauncherFailiure.java @@ -4,4 +4,12 @@ public class LauncherFailiure extends Exception { public LauncherFailiure() { super(); } + + public LauncherFailiure(String message) { + super(message); + } + + public LauncherFailiure(Throwable cause) { + super(cause); + } } diff --git a/src/main/java/org/opengameband/launcher/BasicLauncher.java b/src/main/java/org/opengameband/launcher/BasicLauncher.java index 62155d5..621a2cc 100644 --- a/src/main/java/org/opengameband/launcher/BasicLauncher.java +++ b/src/main/java/org/opengameband/launcher/BasicLauncher.java @@ -8,6 +8,7 @@ import java.io.File; import java.io.IOException; +import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; import java.util.Objects; @@ -26,20 +27,29 @@ public BasicLauncher() { @Override public void start() throws LauncherFailiure { + File installDir = getInstallDir(); + File gameDataDir = getGameDataDir(); + if (installDir == null || gameDataDir == null) { + throw new LauncherFailiure("Launcher directories are not available"); + } try { - switch (System.getProperty("os.name").split(" ")[0]) { + switch (getOsFamily()) { case "Mac": { - Runtime.getRuntime().exec(new String[]{GetMountPoint().getAbsolutePath() + "/Launchers/Official/Minecraft.app/Contents/MacOS/launcher", + Runtime.getRuntime().exec(new String[]{new File(installDir, "Contents/MacOS/launcher").getAbsolutePath(), "--workDir", getGameDataDir().getAbsolutePath()}); + break; } case "Windows": { - Runtime.getRuntime().exec(new String[]{getInstallDir().getAbsolutePath() + "\\Minecraft.exe", + Runtime.getRuntime().exec(new String[]{new File(installDir, "Minecraft.exe").getAbsolutePath(), "--workDir", getGameDataDir().getAbsolutePath()}); + break; } + default: + throw new LauncherFailiure("Unsupported OS: " + System.getProperty("os.name")); } } catch (IOException e) { System.err.println(e.getMessage()); - throw new LauncherFailiure(); + throw new LauncherFailiure(e); } } @@ -61,7 +71,7 @@ public void install() { } private void extract(String file) { - switch (System.getProperty("os.name").split(" ")[0]) { + switch (getOsFamily()) { case "Mac": try { Process p = Runtime.getRuntime().exec("hdiutil attach " + file); @@ -79,12 +89,14 @@ private void extract(String file) { break; case "Linux": throw new RuntimeException("Not Yet Implemented"); + default: + break; } } @Override public File getLauncherDir() { - return new File(GetMountPoint(), "/Launchers/Official"); + return Path.of(GetMountPoint().getAbsolutePath(), "Launchers", "Official").toFile(); } /** @@ -93,11 +105,11 @@ public File getLauncherDir() { @Override public File getInstallDir() { if (GetMountPoint().exists() && GetMountPoint().isDirectory() && GetMountPoint().canRead()) { - switch (System.getProperty("os.name").split(" ")[0]) { + switch (getOsFamily()) { case "Windows": - return new File(getLauncherDir(), "\\win"); + return new File(getLauncherDir(), "win"); case "Mac": - return new File(GetMountPoint(), "/Launchers/Official/Minecraft.app"); + return new File(getLauncherDir(), "Minecraft.app"); } } return null; @@ -106,13 +118,28 @@ public File getInstallDir() { @Override public File getGameDataDir() { if (GetMountPoint().exists() && GetMountPoint().isDirectory()) { - return new File(GetMountPoint(), "/Launchers/Official/Game"); + return new File(getLauncherDir(), "Game"); } return null; } @Override public boolean isInstalled() { - return getInstallDir().exists() && getInstallDir().listFiles().length > 0; + File installDir = getInstallDir(); + return installDir != null && installDir.exists() && installDir.listFiles() != null && installDir.listFiles().length > 0; + } + + private String getOsFamily() { + String os = System.getProperty("os.name", "").toLowerCase(); + if (os.contains("win")) { + return "Windows"; + } + if (os.contains("mac")) { + return "Mac"; + } + if (os.contains("linux")) { + return "Linux"; + } + return "Unknown"; } } diff --git a/src/main/java/org/opengameband/util/DownloadURLs.java b/src/main/java/org/opengameband/util/DownloadURLs.java index b5f69c1..62f6dd1 100644 --- a/src/main/java/org/opengameband/util/DownloadURLs.java +++ b/src/main/java/org/opengameband/util/DownloadURLs.java @@ -4,9 +4,9 @@ * @author Zaprit */ public enum DownloadURLs { - MAC("https://launcher.mojang.com/download/Minecraft.dmg", "/Minecraft.dmg"), - LIN("https://launcher.mojang.com/download/Minecraft.tar.gz", "/Minecraft.tar.gz"), - WIN("https://launcher.mojang.com/download/Minecraft.exe", "\\Minecraft.exe"); + MAC("https://launcher.mojang.com/download/Minecraft.dmg", "Minecraft.dmg"), + LIN("https://launcher.mojang.com/download/Minecraft.tar.gz", "Minecraft.tar.gz"), + WIN("https://launcher.mojang.com/download/Minecraft.exe", "Minecraft.exe"); private String url; private String file; diff --git a/src/main/java/org/opengameband/util/MountPoint.java b/src/main/java/org/opengameband/util/MountPoint.java index c17463f..c6313de 100644 --- a/src/main/java/org/opengameband/util/MountPoint.java +++ b/src/main/java/org/opengameband/util/MountPoint.java @@ -1,6 +1,7 @@ package org.opengameband.util; import java.io.File; +import java.net.URISyntaxException; /** * @author Zaprit @@ -14,6 +15,14 @@ public MountPoint() { * TODO: Add the ability to change this as it may be needed later */ public static File GetMountPoint(){ - return new File(MountPoint.class.getProtectionDomain().getCodeSource().getLocation().getPath()); + try { + File codeSourceLocation = new File(MountPoint.class.getProtectionDomain().getCodeSource().getLocation().toURI()); + if (codeSourceLocation.isFile()) { + return codeSourceLocation.getParentFile(); + } + return codeSourceLocation; + } catch (URISyntaxException e) { + return new File(MountPoint.class.getProtectionDomain().getCodeSource().getLocation().getPath()); + } } } From d07d49e984483da971921b9f74a8a11e3ccef33a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Mar 2026 19:32:02 +0000 Subject: [PATCH 3/3] chore: apply review cleanup and finalize verification Co-authored-by: TheCodingSoldier <257933801+TheCodingSoldier@users.noreply.github.com> --- src/main/java/org/opengameband/launcher/BasicLauncher.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/opengameband/launcher/BasicLauncher.java b/src/main/java/org/opengameband/launcher/BasicLauncher.java index 621a2cc..ecf57df 100644 --- a/src/main/java/org/opengameband/launcher/BasicLauncher.java +++ b/src/main/java/org/opengameband/launcher/BasicLauncher.java @@ -126,7 +126,8 @@ public File getGameDataDir() { @Override public boolean isInstalled() { File installDir = getInstallDir(); - return installDir != null && installDir.exists() && installDir.listFiles() != null && installDir.listFiles().length > 0; + File[] installFiles = installDir == null ? null : installDir.listFiles(); + return installDir != null && installDir.exists() && installFiles != null && installFiles.length > 0; } private String getOsFamily() {