From 06c423a4dd3cae786f4113b57024862afa7c8aec Mon Sep 17 00:00:00 2001 From: Jeffrey Han Date: Sat, 31 Oct 2015 22:20:08 -0400 Subject: [PATCH] Properly detect osu! installations on Windows (using registry keys). Thanks to @ModuleLFS for the idea. Signed-off-by: Jeffrey Han --- src/itdelatrisu/opsu/Options.java | 74 ++++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 22 deletions(-) diff --git a/src/itdelatrisu/opsu/Options.java b/src/itdelatrisu/opsu/Options.java index 5c5c4416..9bf79fac 100644 --- a/src/itdelatrisu/opsu/Options.java +++ b/src/itdelatrisu/opsu/Options.java @@ -41,6 +41,8 @@ import java.util.concurrent.TimeUnit; import java.util.jar.Attributes; import java.util.jar.JarFile; import java.util.jar.Manifest; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.lwjgl.input.Keyboard; import org.newdawn.slick.GameContainer; @@ -51,6 +53,10 @@ import org.newdawn.slick.util.FileSystemLocation; import org.newdawn.slick.util.Log; import org.newdawn.slick.util.ResourceLoader; +import com.sun.jna.platform.win32.Advapi32Util; +import com.sun.jna.platform.win32.Win32Exception; +import com.sun.jna.platform.win32.WinReg; + /** * Handles all user options. */ @@ -73,19 +79,11 @@ public class Options { /** File for storing user options. */ private static final File OPTIONS_FILE = new File(CONFIG_DIR, ".opsu.cfg"); - /** Beatmap directories (where to search for files). */ - private static final String[] BEATMAP_DIRS = { - "C:/Program Files (x86)/osu!/Songs/", - "C:/Program Files/osu!/Songs/", - new File(DATA_DIR, "Songs/").getPath() - }; + /** The default beatmap directory (unless an osu! installation is detected). */ + private static final File BEATMAP_DIR = new File(DATA_DIR, "Songs/"); - /** Skin directories (where to search for skins). */ - private static final String[] SKIN_ROOT_DIRS = { - "C:/Program Files (x86)/osu!/Skins/", - "C:/Program Files/osu!/Skins/", - new File(DATA_DIR, "Skins/").getPath() - }; + /** The default skin directory (unless an osu! installation is detected). */ + private static final File SKIN_ROOT_DIR = new File(DATA_DIR, "Skins/"); /** Cached beatmap database name. */ public static final File BEATMAP_DB = new File(DATA_DIR, ".opsu.db"); @@ -180,6 +178,34 @@ public class Options { return new File("./"); } + /** + * Returns the osu! installation directory. + * @return the directory, or null if not found + */ + private static File getOsuInstallationDirectory() { + if (!System.getProperty("os.name").startsWith("Win")) + return null; // only works on Windows + + // registry location + final WinReg.HKEY rootKey = WinReg.HKEY_CLASSES_ROOT; + final String regKey = "osu\\DefaultIcon"; + final String regValue = null; // default value + final String regPathPattern = "\"(.+)\\\\[^\\/]+\\.exe\""; + + String value; + try { + value = Advapi32Util.registryGetStringValue(rootKey, regKey, regValue); + } catch (Win32Exception e) { + return null; // key/value not found + } + Pattern pattern = Pattern.compile(regPathPattern); + Matcher m = pattern.matcher(value); + if (!m.find()) + return null; + File dir = new File(m.group(1)); + return (dir.isDirectory()) ? dir : null; + } + /** * The theme song string: * {@code filename,title,artist,length(ms)} @@ -1142,15 +1168,17 @@ public class Options { if (beatmapDir != null && beatmapDir.isDirectory()) return beatmapDir; - // search for directory - for (int i = 0; i < BEATMAP_DIRS.length; i++) { - beatmapDir = new File(BEATMAP_DIRS[i]); + // use osu! installation directory, if found + File osuDir = getOsuInstallationDirectory(); + if (osuDir != null) { + beatmapDir = new File(osuDir, BEATMAP_DIR.getName()); if (beatmapDir.isDirectory()) return beatmapDir; } - // none found, create new directory - if (!beatmapDir.mkdir()) + // use default directory + beatmapDir = BEATMAP_DIR; + if (!beatmapDir.isDirectory() && !beatmapDir.mkdir()) ErrorHandler.error(String.format("Failed to create beatmap directory at '%s'.", beatmapDir.getAbsolutePath()), null, false); return beatmapDir; } @@ -1220,15 +1248,17 @@ public class Options { if (skinRootDir != null && skinRootDir.isDirectory()) return skinRootDir; - // search for directory - for (int i = 0; i < SKIN_ROOT_DIRS.length; i++) { - skinRootDir = new File(SKIN_ROOT_DIRS[i]); + // use osu! installation directory, if found + File osuDir = getOsuInstallationDirectory(); + if (osuDir != null) { + skinRootDir = new File(osuDir, SKIN_ROOT_DIR.getName()); if (skinRootDir.isDirectory()) return skinRootDir; } - // none found, create new directory - if (!skinRootDir.mkdir()) + // use default directory + skinRootDir = SKIN_ROOT_DIR; + if (!skinRootDir.isDirectory() && !skinRootDir.mkdir()) ErrorHandler.error(String.format("Failed to create skins directory at '%s'.", skinRootDir.getAbsolutePath()), null, false); return skinRootDir; }