Prevent downloading songs that are already loaded. (base: fluddokt/opsu/76778f8)
- All beatmap set IDs are now stored in a set in OsuGroupList. - OsuParser now checks the directory name for beatmap set IDs if the OsuFile doesn't contain one (for older beatmap formats). Tweaks: - Clear completed downloads when hitting "Import All". - Call Download.updateReadSoFar() upon starting downloads instead of waiting for user to hover over the button (causing an unnecessary delay). Signed-off-by: Jeffrey Han <itdelatrisu@gmail.com>
This commit is contained in:
parent
f56c02864b
commit
be3b94f5db
|
@ -392,8 +392,8 @@ public class Options {
|
||||||
RES_1366_768 (1366, 768),
|
RES_1366_768 (1366, 768),
|
||||||
RES_1440_900 (1440, 900),
|
RES_1440_900 (1440, 900),
|
||||||
RES_1600_900 (1600, 900),
|
RES_1600_900 (1600, 900),
|
||||||
RES_1680_1050 (1680, 1050),
|
|
||||||
RES_1600_1200 (1600, 1200),
|
RES_1600_1200 (1600, 1200),
|
||||||
|
RES_1680_1050 (1680, 1050),
|
||||||
RES_1920_1080 (1920, 1080),
|
RES_1920_1080 (1920, 1080),
|
||||||
RES_1920_1200 (1920, 1200),
|
RES_1920_1200 (1920, 1200),
|
||||||
RES_2560_1440 (2560, 1440),
|
RES_2560_1440 (2560, 1440),
|
||||||
|
|
|
@ -21,6 +21,7 @@ package itdelatrisu.opsu;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
|
@ -47,6 +48,9 @@ public class OsuGroupList {
|
||||||
/** Current list of nodes (subset of parsedNodes, used for searches). */
|
/** Current list of nodes (subset of parsedNodes, used for searches). */
|
||||||
private ArrayList<OsuGroupNode> nodes;
|
private ArrayList<OsuGroupNode> nodes;
|
||||||
|
|
||||||
|
/** Set of all beatmap set IDs for the parsed beatmaps. */
|
||||||
|
private HashSet<Integer> MSIDdb;
|
||||||
|
|
||||||
/** Index of current expanded node (-1 if no node is expanded). */
|
/** Index of current expanded node (-1 if no node is expanded). */
|
||||||
private int expandedIndex;
|
private int expandedIndex;
|
||||||
|
|
||||||
|
@ -68,6 +72,7 @@ public class OsuGroupList {
|
||||||
*/
|
*/
|
||||||
private OsuGroupList() {
|
private OsuGroupList() {
|
||||||
parsedNodes = new ArrayList<OsuGroupNode>();
|
parsedNodes = new ArrayList<OsuGroupNode>();
|
||||||
|
MSIDdb = new HashSet<Integer>();
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,6 +100,12 @@ public class OsuGroupList {
|
||||||
OsuGroupNode node = new OsuGroupNode(osuFiles);
|
OsuGroupNode node = new OsuGroupNode(osuFiles);
|
||||||
parsedNodes.add(node);
|
parsedNodes.add(node);
|
||||||
mapCount += osuFiles.size();
|
mapCount += osuFiles.size();
|
||||||
|
|
||||||
|
// add beatmap set ID to set
|
||||||
|
int msid = osuFiles.get(0).beatmapSetID;
|
||||||
|
if (msid > 0)
|
||||||
|
MSIDdb.add(msid);
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,4 +346,14 @@ public class OsuGroupList {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether or not the list contains the given beatmap set ID.
|
||||||
|
* <p>
|
||||||
|
* 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); }
|
||||||
}
|
}
|
|
@ -37,6 +37,12 @@ import org.newdawn.slick.util.Log;
|
||||||
* Parser for OSU files.
|
* Parser for OSU files.
|
||||||
*/
|
*/
|
||||||
public class OsuParser {
|
public class OsuParser {
|
||||||
|
/** The string lookup database. */
|
||||||
|
private static HashMap<String, String> stringdb = new HashMap<String, String>();
|
||||||
|
|
||||||
|
/** 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. */
|
/** The current file being parsed. */
|
||||||
private static File currentFile;
|
private static File currentFile;
|
||||||
|
|
||||||
|
@ -46,9 +52,6 @@ public class OsuParser {
|
||||||
/** The total number of directories to parse. */
|
/** The total number of directories to parse. */
|
||||||
private static int totalDirectories = -1;
|
private static int totalDirectories = -1;
|
||||||
|
|
||||||
/** The string lookup database. */
|
|
||||||
private static HashMap<String, String> stringdb = new HashMap<String, String>();
|
|
||||||
|
|
||||||
// This class should not be instantiated.
|
// This class should not be instantiated.
|
||||||
private OsuParser() {}
|
private OsuParser() {}
|
||||||
|
|
||||||
|
@ -100,7 +103,7 @@ public class OsuParser {
|
||||||
|
|
||||||
// Parse hit objects only when needed to save time/memory.
|
// Parse hit objects only when needed to save time/memory.
|
||||||
// Change boolean to 'true' to parse them immediately.
|
// 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
|
if (!osuFiles.isEmpty()) { // add entry if non-empty
|
||||||
osuFiles.trimToSize();
|
osuFiles.trimToSize();
|
||||||
|
@ -125,11 +128,12 @@ public class OsuParser {
|
||||||
/**
|
/**
|
||||||
* Parses an OSU file.
|
* Parses an OSU file.
|
||||||
* @param file the file to parse
|
* @param file the file to parse
|
||||||
|
* @param dir the directory containing the beatmap
|
||||||
* @param osuFiles the song group
|
* @param osuFiles the song group
|
||||||
* @param parseObjects if true, hit objects will be fully parsed now
|
* @param parseObjects if true, hit objects will be fully parsed now
|
||||||
* @return the new OsuFile object
|
* @return the new OsuFile object
|
||||||
*/
|
*/
|
||||||
public static OsuFile parseFile(File file, ArrayList<OsuFile> osuFiles, boolean parseObjects) {
|
private static OsuFile parseFile(File file, File dir, ArrayList<OsuFile> osuFiles, boolean parseObjects) {
|
||||||
OsuFile osu = new OsuFile(file);
|
OsuFile osu = new OsuFile(file);
|
||||||
|
|
||||||
try (BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"))) {
|
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'.",
|
Log.warn(String.format("Failed to read metadata '%s' for file '%s'.",
|
||||||
line, file.getAbsolutePath()), e);
|
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;
|
break;
|
||||||
case "[Difficulty]":
|
case "[Difficulty]":
|
||||||
|
|
|
@ -165,6 +165,7 @@ public class Download {
|
||||||
rbc = new ReadableByteChannelWrapper(readableByteChannel);
|
rbc = new ReadableByteChannelWrapper(readableByteChannel);
|
||||||
fos = fileOutputStream;
|
fos = fileOutputStream;
|
||||||
status = Status.DOWNLOADING;
|
status = Status.DOWNLOADING;
|
||||||
|
updateReadSoFar();
|
||||||
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
|
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
|
||||||
if (status == Status.DOWNLOADING) { // not interrupted
|
if (status == Status.DOWNLOADING) { // not interrupted
|
||||||
status = Status.COMPLETE;
|
status = Status.COMPLETE;
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
package itdelatrisu.opsu.downloads;
|
package itdelatrisu.opsu.downloads;
|
||||||
|
|
||||||
import itdelatrisu.opsu.ErrorHandler;
|
import itdelatrisu.opsu.ErrorHandler;
|
||||||
|
import itdelatrisu.opsu.downloads.Download.Status;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
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<DownloadNode> 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).
|
* Shows a confirmation dialog (used before exiting the game).
|
||||||
* @return true if user selects "yes", false otherwise
|
* @return true if user selects "yes", false otherwise
|
||||||
|
|
|
@ -21,6 +21,7 @@ package itdelatrisu.opsu.downloads;
|
||||||
import itdelatrisu.opsu.ErrorHandler;
|
import itdelatrisu.opsu.ErrorHandler;
|
||||||
import itdelatrisu.opsu.GameImage;
|
import itdelatrisu.opsu.GameImage;
|
||||||
import itdelatrisu.opsu.Options;
|
import itdelatrisu.opsu.Options;
|
||||||
|
import itdelatrisu.opsu.OsuGroupList;
|
||||||
import itdelatrisu.opsu.Utils;
|
import itdelatrisu.opsu.Utils;
|
||||||
import itdelatrisu.opsu.downloads.Download.Status;
|
import itdelatrisu.opsu.downloads.Download.Status;
|
||||||
|
|
||||||
|
@ -296,6 +297,12 @@ public class DownloadNode {
|
||||||
g.setColor((focus) ? BG_FOCUS : (hover) ? BG_HOVER : BG_NORMAL);
|
g.setColor((focus) ? BG_FOCUS : (hover) ? BG_HOVER : BG_NORMAL);
|
||||||
g.fillRect(buttonBaseX, y, buttonWidth, buttonHeight);
|
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
|
// download progress
|
||||||
if (dl != null) {
|
if (dl != null) {
|
||||||
float progress = dl.getProgress();
|
float progress = dl.getProgress();
|
||||||
|
@ -349,7 +356,7 @@ public class DownloadNode {
|
||||||
else if (status == Download.Status.WAITING)
|
else if (status == Download.Status.WAITING)
|
||||||
info = String.format("%s...", status.getName());
|
info = String.format("%s...", status.getName());
|
||||||
else {
|
else {
|
||||||
if (hover)
|
if (hover && status == Download.Status.DOWNLOADING)
|
||||||
info = String.format("%s: %s left (%s)", status.getName(), download.getTimeRemaining(), download.getDownloadSpeed());
|
info = String.format("%s: %s left (%s)", status.getName(), download.getTimeRemaining(), download.getDownloadSpeed());
|
||||||
else
|
else
|
||||||
info = String.format("%s: %.1f%% (%s/%s)", status.getName(), progress,
|
info = String.format("%s: %.1f%% (%s/%s)", status.getName(), progress,
|
||||||
|
|
|
@ -438,6 +438,12 @@ public class DownloadsMenu extends BasicGameState {
|
||||||
if (index >= nodes.length)
|
if (index >= nodes.length)
|
||||||
break;
|
break;
|
||||||
if (DownloadNode.resultContains(x, y, i)) {
|
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);
|
SoundController.playSound(SoundEffect.MENUCLICK);
|
||||||
if (index == focusResult) {
|
if (index == focusResult) {
|
||||||
if (focusTimer >= FOCUS_DELAY) {
|
if (focusTimer >= FOCUS_DELAY) {
|
||||||
|
@ -445,7 +451,6 @@ public class DownloadsMenu extends BasicGameState {
|
||||||
focusTimer = 0;
|
focusTimer = 0;
|
||||||
} else {
|
} else {
|
||||||
// start download
|
// start download
|
||||||
DownloadNode node = nodes[index];
|
|
||||||
if (!DownloadList.get().contains(node.getID())) {
|
if (!DownloadList.get().contains(node.getID())) {
|
||||||
DownloadList.get().addNode(node);
|
DownloadList.get().addNode(node);
|
||||||
node.createDownload(server);
|
node.createDownload(server);
|
||||||
|
@ -515,6 +520,7 @@ public class DownloadsMenu extends BasicGameState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DownloadList.get().clearDownloads(Download.Status.COMPLETE);
|
||||||
importThread = null;
|
importThread = null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue
Block a user