Replay importing

This commit is contained in:
fd 2015-04-01 22:10:36 -04:00
parent 66bd97242f
commit a49b5bc945
12 changed files with 156 additions and 10 deletions

View File

@ -1235,6 +1235,7 @@ public class GameData {
scoreData.perfect = (comboMax == fullObjectCount);
scoreData.mods = GameMod.getModState();
scoreData.replayString = (replay == null) ? null : replay.getReplayFilename();
scoreData.playerName = "OpsuPlayer"; //TODO?
return scoreData;
}

View File

@ -95,6 +95,9 @@ public class Options {
/** The replay directory (created when needed). */
private static File replayDir;
/** The replay import directory. */
private static File replayImportDir;
/** The current skin directory (for user skins). */
private static File skinDir;
@ -825,6 +828,19 @@ public class Options {
return oszDir;
}
/**
* Returns the replay import directory.
* If invalid, this will create and return a "SongPacks" directory.
* @return the OSZ archive directory
*/
public static File getReplayImportDir() {
if (replayImportDir != null && replayImportDir.isDirectory())
return replayImportDir;
replayImportDir = new File(DATA_DIR, "ReplayImport/");
replayImportDir.mkdir();
return replayImportDir;
}
/**
* Returns the screenshot directory.
* If invalid, this will return a "Screenshot" directory.

View File

@ -180,6 +180,8 @@ public class OsuFile implements Comparable<OsuFile> {
/** Combo colors (max 8). */
public Color[] combo;
public String md5Hash;
/**
* [HitObjects]
*/

View File

@ -26,6 +26,7 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
@ -56,6 +57,10 @@ public class OsuGroupList {
/** Set of all beatmap set IDs for the parsed beatmaps. */
private HashSet<Integer> MSIDdb;
/** Set of all beatmap set IDs for the parsed beatmaps. */
public HashMap<String, OsuFile> beatmapHashesToFile;
/** Index of current expanded node (-1 if no node is expanded). */
private int expandedIndex;
@ -81,6 +86,7 @@ public class OsuGroupList {
private OsuGroupList() {
parsedNodes = new ArrayList<OsuGroupNode>();
MSIDdb = new HashSet<Integer>();
beatmapHashesToFile = new HashMap<String, OsuFile>();
reset();
}
@ -114,6 +120,9 @@ public class OsuGroupList {
int msid = osuFiles.get(0).beatmapSetID;
if (msid > 0)
MSIDdb.add(msid);
for(OsuFile f : osuFiles) {
beatmapHashesToFile.put(f.md5Hash, f);
}
return node;
}
@ -498,4 +507,8 @@ public class OsuGroupList {
* @return true if id is in the list
*/
public boolean containsBeatmapSetID(int id) { return MSIDdb.contains(id); }
public OsuFile getFileFromBeatmapHash(String beatmapHash) {
return beatmapHashesToFile.get(beatmapHash);
}
}

View File

@ -587,6 +587,8 @@ public class OsuParser {
if (parseObjects)
parseHitObjects(osu);
osu.md5Hash = Utils.getMD5(file);
return osu;
}

View File

@ -77,6 +77,8 @@ public class ScoreData implements Comparable<ScoreData> {
/** The tooltip string. */
private String tooltip;
public String playerName;
/** Drawing values. */
private static float baseX, baseY, buttonWidth, buttonHeight, buttonOffset;
@ -163,6 +165,7 @@ public class ScoreData implements Comparable<ScoreData> {
this.perfect = rs.getBoolean(16);
this.mods = rs.getInt(17);
this.replayString = rs.getString(18);
this.playerName = rs.getString(19);
}
/**
@ -259,7 +262,7 @@ public class ScoreData implements Comparable<ScoreData> {
// hit counts (custom: osu! shows user instead, above score)
Utils.FONT_SMALL.drawString(
textX, y + textOffset + Utils.FONT_MEDIUM.getLineHeight(),
String.format("300:%d 100:%d 50:%d Miss:%d", hit300, hit100, hit50, miss),
String.format("300:%d 100:%d 50:%d Miss:%d Name:%s", hit300, hit100, hit50, miss, getPlayerName()),
Color.white
);
@ -330,6 +333,11 @@ public class ScoreData implements Comparable<ScoreData> {
);
}
public String getPlayerName() {
if(playerName == null)
return "Null Name";
return playerName;
}
@Override
public int compareTo(ScoreData that) {
if (this.score != that.score)

View File

@ -43,7 +43,7 @@ public class OsuDB {
* Current database version.
* This value should be changed whenever the database format changes.
*/
private static final String DATABASE_VERSION = "2014-03-08";
private static final String DATABASE_VERSION = "2015-03-30";
/** Minimum batch size ratio ({@code batchSize/cacheSize}) to invoke batch loading. */
private static final float LOAD_BATCH_MIN_RATIO = 0.2f;
@ -83,7 +83,7 @@ public class OsuDB {
insertStmt = connection.prepareStatement(
"INSERT INTO beatmaps VALUES (" +
"?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, " +
"?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
"?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
);
selectStmt = connection.prepareStatement("SELECT * FROM beatmaps WHERE dir = ? AND file = ?");
deleteMapStmt = connection.prepareStatement("DELETE FROM beatmaps WHERE dir = ? AND file = ?");
@ -116,7 +116,8 @@ public class OsuDB {
"bpmMin INTEGER, bpmMax INTEGER, endTime INTEGER, " +
"audioFile TEXT, audioLeadIn INTEGER, previewTime INTEGER, countdown INTEGER, sampleSet TEXT, stackLeniency REAL, " +
"mode INTEGER, letterboxInBreaks BOOLEAN, widescreenStoryboard BOOLEAN, epilepsyWarning BOOLEAN, " +
"bg TEXT, timingPoints TEXT, breaks TEXT, combo TEXT" +
"bg TEXT, timingPoints TEXT, breaks TEXT, combo TEXT," +
"md5hash TEXT" +
"); " +
"CREATE TABLE IF NOT EXISTS info (" +
"key TEXT NOT NULL UNIQUE, value TEXT" +
@ -333,7 +334,8 @@ public class OsuDB {
stmt.setString(37, osu.timingPointsToString());
stmt.setString(38, osu.breaksToString());
stmt.setString(39, osu.comboToString());
} catch (SQLException e) {
stmt.setString(40, osu.md5Hash);
} catch (SQLException e) {
throw e;
} catch (Exception e) {
throw new SQLException(e);
@ -470,6 +472,7 @@ public class OsuDB {
osu.widescreenStoryboard = rs.getBoolean(34);
osu.epilepsyWarning = rs.getBoolean(35);
osu.bg = OsuParser.getDBString(rs.getString(36));
osu.md5Hash = OsuParser.getDBString(rs.getString(40));
} catch (SQLException e) {
throw e;
} catch (Exception e) {

View File

@ -45,7 +45,7 @@ public class ScoreDB {
* This value should be changed whenever the database format changes.
* Add any update queries to the {@link #getUpdateQueries(int)} method.
*/
private static final int DATABASE_VERSION = 20140311;
private static final int DATABASE_VERSION = 20150401;
/**
* Returns a list of SQL queries to apply, in order, to update from
@ -57,6 +57,8 @@ public class ScoreDB {
List<String> list = new LinkedList<String>();
if (version < 20140311)
list.add("ALTER TABLE scores ADD COLUMN replay TEXT");
if (version < 20150401)
list.add("ALTER TABLE scores ADD COLUMN playerName TEXT");
/* add future updates here */
@ -96,7 +98,7 @@ public class ScoreDB {
// prepare sql statements
try {
insertStmt = connection.prepareStatement(
"INSERT INTO scores VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
"INSERT OR IGNORE INTO scores VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
);
selectMapStmt = connection.prepareStatement(
"SELECT * FROM scores WHERE " +
@ -137,7 +139,8 @@ public class ScoreDB {
"combo INTEGER, " +
"perfect BOOLEAN, " +
"mods INTEGER, " +
"replay TEXT" +
"replay TEXT," +
"playerName TEXT"+
");" +
"CREATE TABLE IF NOT EXISTS info (" +
"key TEXT NOT NULL UNIQUE, value TEXT" +
@ -283,6 +286,8 @@ public class ScoreDB {
stmt.setInt(15, data.combo);
stmt.setBoolean(16, data.perfect);
stmt.setInt(17, data.mods);
stmt.setString(19, data.playerName);
}
/**

View File

@ -18,6 +18,7 @@
package itdelatrisu.opsu.io;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
@ -50,7 +51,7 @@ public class OsuReader {
* @param source the input stream to read from
*/
public OsuReader(InputStream source) {
this.reader = new DataInputStream(source);
this.reader = new DataInputStream(new BufferedInputStream(source));
}
/**

View File

@ -19,15 +19,20 @@
package itdelatrisu.opsu.replay;
import itdelatrisu.opsu.ErrorHandler;
import itdelatrisu.opsu.GameMod;
import itdelatrisu.opsu.Options;
import itdelatrisu.opsu.OsuFile;
import itdelatrisu.opsu.ScoreData;
import itdelatrisu.opsu.Utils;
import itdelatrisu.opsu.io.OsuReader;
import itdelatrisu.opsu.io.OsuWriter;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.CharBuffer;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.StandardCharsets;
@ -100,6 +105,8 @@ public class Replay {
/** Seed. (?) */
public int seed;
private ScoreData scoreData;
/** Seed string. */
private static final String SEED_STRING = "-12345";
@ -131,6 +138,41 @@ public class Replay {
loaded = true;
}
/**
* Returns a ScoreData object encapsulating all game data.
* If score data already exists, the existing object will be returned
* (i.e. this will not overwrite existing data).
* @param osu the OsuFile
* @return the ScoreData object
*/
public ScoreData getScoreData(OsuFile osu) {
if (scoreData != null)
return scoreData;
scoreData = new ScoreData();
scoreData.timestamp = file.lastModified() / 1000L;
scoreData.MID = osu.beatmapID;
scoreData.MSID = osu.beatmapSetID;
scoreData.title = osu.title;
scoreData.artist = osu.artist;
scoreData.creator = osu.creator;
scoreData.version = osu.version;
scoreData.hit300 = hit300;
scoreData.hit100 = hit100;
scoreData.hit50 = hit50;
scoreData.geki = geki;
scoreData.katu = katu;
scoreData.miss = miss;
scoreData.score = score;
scoreData.combo = combo;
scoreData.perfect = perfect;
scoreData.mods = mods;
scoreData.replayString = file!=null ? file.getName() : getReplayFilename();
scoreData.playerName = playerName!=null ? playerName : "No Name";
return scoreData;
}
/**
* Loads the replay header data.
* @param reader the associated reader
@ -139,6 +181,7 @@ public class Replay {
private void loadHeader(OsuReader reader) throws IOException {
this.mode = reader.readByte();
this.version = reader.readInt();
System.out.println("Header:"+file.getName()+" "+mode+" "+version);
this.beatmapHash = reader.readString();
this.playerName = reader.readString();
this.replayHash = reader.readString();
@ -232,7 +275,7 @@ public class Replay {
new Thread() {
@Override
public void run() {
try (FileOutputStream out = new FileOutputStream(file)) {
try (OutputStream out = new BufferedOutputStream(new FileOutputStream(file))) {
OsuWriter writer = new OsuWriter(out);
// header

View File

@ -0,0 +1,44 @@
package itdelatrisu.opsu.replay;
import itdelatrisu.opsu.ErrorHandler;
import itdelatrisu.opsu.Options;
import itdelatrisu.opsu.OsuFile;
import itdelatrisu.opsu.OsuGroupList;
import itdelatrisu.opsu.ScoreData;
import itdelatrisu.opsu.db.ScoreDB;
import java.io.File;
import java.io.IOException;
public class ReplayImporter {
public static void importAllReplaysFromDir(File dir) {
System.out.println(OsuGroupList.get().beatmapHashesToFile);
for (File replayToImport : dir.listFiles()) {
try {
Replay r = new Replay(replayToImport);
r.load();
OsuFile oFile = OsuGroupList.get().getFileFromBeatmapHash(r.beatmapHash);
if(oFile != null){
//ErrorHandler.error("Importing"+replayToImport+" forBeatmap:"+oFile, null, false);
ScoreData data = r.getScoreData(oFile);
File moveToFile = new File(Options.getReplayDir(),replayToImport.getName());
System.out.println("Moving "+replayToImport+" to "+moveToFile);
if(
!replayToImport.renameTo(moveToFile)
){
System.out.println("Rename Failed "+moveToFile);
}
data.replayString = replayToImport.getName().substring(0, replayToImport.getName().length()-4);
ScoreDB.addScore(data);;
} else {
//ErrorHandler.error("Could not find beatmap for replay "+replayToImport, null, false);
}
} catch (IOException e) {
// TODO Auto-generated catch block
//e.printStackTrace();
System.out.println(e);
}
}
}
}

View File

@ -18,9 +18,11 @@
package itdelatrisu.opsu.states;
import itdelatrisu.opsu.ErrorHandler;
import itdelatrisu.opsu.GameImage;
import itdelatrisu.opsu.Opsu;
import itdelatrisu.opsu.Options;
import itdelatrisu.opsu.OsuFile;
import itdelatrisu.opsu.OsuGroupList;
import itdelatrisu.opsu.OsuParser;
import itdelatrisu.opsu.OszUnpacker;
@ -28,8 +30,11 @@ import itdelatrisu.opsu.UI;
import itdelatrisu.opsu.Utils;
import itdelatrisu.opsu.audio.MusicController;
import itdelatrisu.opsu.audio.SoundController;
import itdelatrisu.opsu.replay.Replay;
import itdelatrisu.opsu.replay.ReplayImporter;
import java.io.File;
import java.io.IOException;
import org.newdawn.slick.Color;
import org.newdawn.slick.GameContainer;
@ -39,6 +44,7 @@ import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.state.BasicGameState;
import org.newdawn.slick.state.StateBasedGame;
import org.newdawn.slick.util.Log;
/**
* "Splash Screen" state.
@ -105,6 +111,8 @@ public class Splash extends BasicGameState {
// parse song directory
OsuParser.parseAllFiles(beatmapDir);
ReplayImporter.importAllReplaysFromDir(Options.getReplayImportDir());
// load sounds
SoundController.init();