diff --git a/src/itdelatrisu/opsu/Options.java b/src/itdelatrisu/opsu/Options.java index 5d261d33..33873642 100644 --- a/src/itdelatrisu/opsu/Options.java +++ b/src/itdelatrisu/opsu/Options.java @@ -392,8 +392,8 @@ public class Options { RES_1366_768 (1366, 768), RES_1440_900 (1440, 900), RES_1600_900 (1600, 900), - RES_1680_1050 (1680, 1050), RES_1600_1200 (1600, 1200), + RES_1680_1050 (1680, 1050), RES_1920_1080 (1920, 1080), RES_1920_1200 (1920, 1200), RES_2560_1440 (2560, 1440), diff --git a/src/itdelatrisu/opsu/OsuGroupList.java b/src/itdelatrisu/opsu/OsuGroupList.java index ffb57b6c..ce95ebc6 100644 --- a/src/itdelatrisu/opsu/OsuGroupList.java +++ b/src/itdelatrisu/opsu/OsuGroupList.java @@ -21,6 +21,7 @@ package itdelatrisu.opsu; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.regex.Matcher; @@ -47,6 +48,9 @@ public class OsuGroupList { /** Current list of nodes (subset of parsedNodes, used for searches). */ private ArrayList nodes; + /** Set of all beatmap set IDs for the parsed beatmaps. */ + private HashSet MSIDdb; + /** Index of current expanded node (-1 if no node is expanded). */ private int expandedIndex; @@ -68,6 +72,7 @@ public class OsuGroupList { */ private OsuGroupList() { parsedNodes = new ArrayList(); + MSIDdb = new HashSet(); reset(); } @@ -95,6 +100,12 @@ public class OsuGroupList { OsuGroupNode node = new OsuGroupNode(osuFiles); parsedNodes.add(node); mapCount += osuFiles.size(); + + // add beatmap set ID to set + int msid = osuFiles.get(0).beatmapSetID; + if (msid > 0) + MSIDdb.add(msid); + return node; } @@ -335,4 +346,14 @@ public class OsuGroupList { return true; } + + /** + * Returns whether or not the list contains the given beatmap set ID. + *

+ * Note that IDs for older maps might have been improperly parsed, so + * there is no guarantee that this method will return an accurate value. + * @param id the beatmap set ID to check + * @return true if id is in the list + */ + public boolean containsBeatmapSetID(int id) { return MSIDdb.contains(id); } } \ No newline at end of file diff --git a/src/itdelatrisu/opsu/OsuParser.java b/src/itdelatrisu/opsu/OsuParser.java index 48038441..5c424a7e 100644 --- a/src/itdelatrisu/opsu/OsuParser.java +++ b/src/itdelatrisu/opsu/OsuParser.java @@ -37,6 +37,12 @@ import org.newdawn.slick.util.Log; * Parser for OSU files. */ public class OsuParser { + /** The string lookup database. */ + private static HashMap stringdb = new HashMap(); + + /** The expected pattern for beatmap directories, used to find beatmap set IDs. */ + private static final String DIR_MSID_PATTERN = "^\\d+ .*"; + /** The current file being parsed. */ private static File currentFile; @@ -46,9 +52,6 @@ public class OsuParser { /** The total number of directories to parse. */ private static int totalDirectories = -1; - /** The string lookup database. */ - private static HashMap stringdb = new HashMap(); - // This class should not be instantiated. private OsuParser() {} @@ -100,7 +103,7 @@ public class OsuParser { // Parse hit objects only when needed to save time/memory. // Change boolean to 'true' to parse them immediately. - parseFile(file, osuFiles, false); + parseFile(file, dir, osuFiles, false); } if (!osuFiles.isEmpty()) { // add entry if non-empty osuFiles.trimToSize(); @@ -125,11 +128,12 @@ public class OsuParser { /** * Parses an OSU file. * @param file the file to parse + * @param dir the directory containing the beatmap * @param osuFiles the song group * @param parseObjects if true, hit objects will be fully parsed now * @return the new OsuFile object */ - public static OsuFile parseFile(File file, ArrayList osuFiles, boolean parseObjects) { + private static OsuFile parseFile(File file, File dir, ArrayList osuFiles, boolean parseObjects) { OsuFile osu = new OsuFile(file); try (BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"))) { @@ -295,6 +299,13 @@ public class OsuParser { Log.warn(String.format("Failed to read metadata '%s' for file '%s'.", line, file.getAbsolutePath()), e); } + if (osu.beatmapSetID <= 0) { // try to determine MSID from directory name + if (dir != null && dir.isDirectory()) { + String dirName = dir.getName(); + if (!dirName.isEmpty() && dirName.matches(DIR_MSID_PATTERN)) + osu.beatmapSetID = Integer.parseInt(dirName.substring(0, dirName.indexOf(' '))); + } + } } break; case "[Difficulty]": diff --git a/src/itdelatrisu/opsu/downloads/Download.java b/src/itdelatrisu/opsu/downloads/Download.java index 81c47ee5..698f24c6 100644 --- a/src/itdelatrisu/opsu/downloads/Download.java +++ b/src/itdelatrisu/opsu/downloads/Download.java @@ -165,6 +165,7 @@ public class Download { rbc = new ReadableByteChannelWrapper(readableByteChannel); fos = fileOutputStream; status = Status.DOWNLOADING; + updateReadSoFar(); fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); if (status == Status.DOWNLOADING) { // not interrupted status = Status.COMPLETE; diff --git a/src/itdelatrisu/opsu/downloads/DownloadList.java b/src/itdelatrisu/opsu/downloads/DownloadList.java index 4af6ac9f..10cfec54 100644 --- a/src/itdelatrisu/opsu/downloads/DownloadList.java +++ b/src/itdelatrisu/opsu/downloads/DownloadList.java @@ -19,6 +19,7 @@ package itdelatrisu.opsu.downloads; import itdelatrisu.opsu.ErrorHandler; +import itdelatrisu.opsu.downloads.Download.Status; import java.util.ArrayList; import java.util.HashMap; @@ -143,6 +144,23 @@ public class DownloadList { } } + /** + * Removes all downloads with the given status from the list. + * @param status the download status + */ + public void clearDownloads(Status status) { + Iterator iter = nodes.iterator(); + while (iter.hasNext()) { + DownloadNode node = iter.next(); + Download dl = node.getDownload(); + if (dl != null && dl.getStatus() == status) { + node.clearDownload(); + iter.remove(); + map.remove(node.getID()); + } + } + } + /** * Shows a confirmation dialog (used before exiting the game). * @return true if user selects "yes", false otherwise diff --git a/src/itdelatrisu/opsu/downloads/DownloadNode.java b/src/itdelatrisu/opsu/downloads/DownloadNode.java index 6cf06890..28ec1ee1 100644 --- a/src/itdelatrisu/opsu/downloads/DownloadNode.java +++ b/src/itdelatrisu/opsu/downloads/DownloadNode.java @@ -21,6 +21,7 @@ package itdelatrisu.opsu.downloads; import itdelatrisu.opsu.ErrorHandler; import itdelatrisu.opsu.GameImage; import itdelatrisu.opsu.Options; +import itdelatrisu.opsu.OsuGroupList; import itdelatrisu.opsu.Utils; import itdelatrisu.opsu.downloads.Download.Status; @@ -296,6 +297,12 @@ public class DownloadNode { g.setColor((focus) ? BG_FOCUS : (hover) ? BG_HOVER : BG_NORMAL); g.fillRect(buttonBaseX, y, buttonWidth, buttonHeight); + // map is already loaded + if (OsuGroupList.get().containsBeatmapSetID(beatmapSetID)) { + g.setColor(Utils.COLOR_BLUE_BUTTON); + g.fillRect(buttonBaseX, y, buttonWidth, buttonHeight); + } + // download progress if (dl != null) { float progress = dl.getProgress(); @@ -349,7 +356,7 @@ public class DownloadNode { else if (status == Download.Status.WAITING) info = String.format("%s...", status.getName()); else { - if (hover) + if (hover && status == Download.Status.DOWNLOADING) info = String.format("%s: %s left (%s)", status.getName(), download.getTimeRemaining(), download.getDownloadSpeed()); else info = String.format("%s: %.1f%% (%s/%s)", status.getName(), progress, diff --git a/src/itdelatrisu/opsu/states/DownloadsMenu.java b/src/itdelatrisu/opsu/states/DownloadsMenu.java index 0a7b2dfa..ac3c6703 100644 --- a/src/itdelatrisu/opsu/states/DownloadsMenu.java +++ b/src/itdelatrisu/opsu/states/DownloadsMenu.java @@ -438,6 +438,12 @@ public class DownloadsMenu extends BasicGameState { if (index >= nodes.length) break; if (DownloadNode.resultContains(x, y, i)) { + DownloadNode node = nodes[index]; + + // check if map is already loaded + if (OsuGroupList.get().containsBeatmapSetID(node.getID())) + return; + SoundController.playSound(SoundEffect.MENUCLICK); if (index == focusResult) { if (focusTimer >= FOCUS_DELAY) { @@ -445,7 +451,6 @@ public class DownloadsMenu extends BasicGameState { focusTimer = 0; } else { // start download - DownloadNode node = nodes[index]; if (!DownloadList.get().contains(node.getID())) { DownloadList.get().addNode(node); node.createDownload(server); @@ -515,6 +520,7 @@ public class DownloadsMenu extends BasicGameState { } } + DownloadList.get().clearDownloads(Download.Status.COMPLETE); importThread = null; } };