save offset per song and save it to db (from itdelatrisu/opsu@e023780)

This commit is contained in:
yugecin 2018-10-02 23:50:13 +02:00
parent 54ce595c7f
commit 5b324bf6ba
No known key found for this signature in database
GPG Key ID: 2C5AC035A7068E44
6 changed files with 75 additions and 22 deletions

View File

@ -22,6 +22,7 @@ import itdelatrisu.opsu.Utils;
import itdelatrisu.opsu.beatmap.Beatmap; import itdelatrisu.opsu.beatmap.Beatmap;
import itdelatrisu.opsu.beatmap.TimingPoint; import itdelatrisu.opsu.beatmap.TimingPoint;
import itdelatrisu.opsu.states.Game; import itdelatrisu.opsu.states.Game;
import yugecin.opsudance.options.Options;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -358,10 +359,14 @@ public class MusicController {
* If no track is loaded, 0 will be returned. * If no track is loaded, 0 will be returned.
*/ */
public static int getPosition() { public static int getPosition() {
int offset = OPTION_MUSIC_OFFSET.val;
if (lastBeatmap != null)
offset += lastBeatmap.localMusicOffset;
if (isPlaying()) if (isPlaying())
return (int) (player.getPosition() * 1000 + OPTION_MUSIC_OFFSET.val + Game.currentMapMusicOffset); return (int) (player.getPosition() * 1000 + offset);
else if (isPaused()) else if (isPaused())
return Math.max((int) (pauseTime * 1000 + OPTION_MUSIC_OFFSET.val + Game.currentMapMusicOffset), 0); return Math.max((int) (pauseTime * 1000 + offset), 0);
else else
return 0; return 0;
} }

View File

@ -89,6 +89,9 @@ public class Beatmap implements Comparable<Beatmap> {
/** The last time this beatmap was played (timestamp). */ /** The last time this beatmap was played (timestamp). */
public long lastPlayed = 0; public long lastPlayed = 0;
/** The local music offset. */
public int localMusicOffset = 0;
/** /**
* [General] * [General]
*/ */

View File

@ -20,6 +20,7 @@ package itdelatrisu.opsu.db;
import itdelatrisu.opsu.beatmap.Beatmap; import itdelatrisu.opsu.beatmap.Beatmap;
import itdelatrisu.opsu.beatmap.BeatmapParser; import itdelatrisu.opsu.beatmap.BeatmapParser;
import yugecin.opsudance.core.errorhandling.ErrorHandler;
import java.io.File; import java.io.File;
import java.sql.Connection; import java.sql.Connection;
@ -47,7 +48,7 @@ public class BeatmapDB {
* This value should be changed whenever the database format changes. * This value should be changed whenever the database format changes.
* Add any update queries to the {@link #getUpdateQueries(int)} method. * Add any update queries to the {@link #getUpdateQueries(int)} method.
*/ */
private static final int DATABASE_VERSION = 20161222; private static final int DATABASE_VERSION = 20161225;
/** /**
* Returns a list of SQL queries to apply, in order, to update from * Returns a list of SQL queries to apply, in order, to update from
@ -64,6 +65,10 @@ public class BeatmapDB {
list.add("ALTER TABLE beatmaps ADD COLUMN lastPlayed INTEGER"); list.add("ALTER TABLE beatmaps ADD COLUMN lastPlayed INTEGER");
list.add("UPDATE beatmaps SET dateAdded = 0, favorite = 0, playCount = 0, lastPlayed = 0"); list.add("UPDATE beatmaps SET dateAdded = 0, favorite = 0, playCount = 0, lastPlayed = 0");
} }
if (version < 20161225) {
list.add("ALTER TABLE beatmaps ADD COLUMN localOffset INTEGER");
list.add("UPDATE beatmaps SET localOffset = 0");
}
/* add future updates here */ /* add future updates here */
@ -85,7 +90,7 @@ public class BeatmapDB {
/** Query statements. */ /** Query statements. */
private static PreparedStatement private static PreparedStatement
insertStmt, selectStmt, deleteMapStmt, deleteGroupStmt, insertStmt, selectStmt, deleteMapStmt, deleteGroupStmt,
setStarsStmt, updatePlayStatsStmt, setFavoriteStmt, updateSizeStmt; setStarsStmt, updatePlayStatsStmt, setFavoriteStmt, setLocalOffsetStmt, updateSizeStmt;
/** Current size of beatmap cache table. */ /** Current size of beatmap cache table. */
private static int cacheSize = -1; private static int cacheSize = -1;
@ -121,7 +126,7 @@ public class BeatmapDB {
"INSERT INTO beatmaps VALUES (" + "INSERT INTO beatmaps VALUES (" +
"?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?," + "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?," +
"?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?," + "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?," +
"?, ?, ?, ?, ?, ?" + "?, ?, ?, ?, ?, ?, ?" +
")" ")"
); );
selectStmt = connection.prepareStatement("SELECT * FROM beatmaps WHERE dir = ? AND file = ?"); selectStmt = connection.prepareStatement("SELECT * FROM beatmaps WHERE dir = ? AND file = ?");
@ -130,6 +135,7 @@ public class BeatmapDB {
setStarsStmt = connection.prepareStatement("UPDATE beatmaps SET stars = ? WHERE dir = ? AND file = ?"); setStarsStmt = connection.prepareStatement("UPDATE beatmaps SET stars = ? WHERE dir = ? AND file = ?");
updatePlayStatsStmt = connection.prepareStatement("UPDATE beatmaps SET playCount = ?, lastPlayed = ? WHERE dir = ? AND file = ?"); updatePlayStatsStmt = connection.prepareStatement("UPDATE beatmaps SET playCount = ?, lastPlayed = ? WHERE dir = ? AND file = ?");
setFavoriteStmt = connection.prepareStatement("UPDATE beatmaps SET favorite = ? WHERE dir = ? AND file = ?"); setFavoriteStmt = connection.prepareStatement("UPDATE beatmaps SET favorite = ? WHERE dir = ? AND file = ?");
setLocalOffsetStmt = connection.prepareStatement("UPDATE beatmaps SET localOffset = ? WHERE dir = ? AND file = ?");
} catch (SQLException e) { } catch (SQLException e) {
explode("Failed to prepare beatmap statements.", e, DEFAULT_OPTIONS); explode("Failed to prepare beatmap statements.", e, DEFAULT_OPTIONS);
} }
@ -153,7 +159,7 @@ public class BeatmapDB {
"mode INTEGER, letterboxInBreaks BOOLEAN, widescreenStoryboard BOOLEAN, epilepsyWarning BOOLEAN, " + "mode INTEGER, letterboxInBreaks BOOLEAN, widescreenStoryboard BOOLEAN, epilepsyWarning BOOLEAN, " +
"bg TEXT, sliderBorder TEXT, timingPoints TEXT, breaks TEXT, combo TEXT, " + "bg TEXT, sliderBorder TEXT, timingPoints TEXT, breaks TEXT, combo TEXT, " +
"md5hash TEXT, stars REAL, " + "md5hash TEXT, stars REAL, " +
"dateAdded INTEGER, favorite BOOLEAN, playCount INTEGER, lastPlayed INTEGER" + "dateAdded INTEGER, favorite BOOLEAN, playCount INTEGER, lastPlayed INTEGER, localOffset INTEGER" +
"); " + "); " +
"CREATE TABLE IF NOT EXISTS info (" + "CREATE TABLE IF NOT EXISTS info (" +
"key TEXT NOT NULL UNIQUE, value TEXT" + "key TEXT NOT NULL UNIQUE, value TEXT" +
@ -402,6 +408,7 @@ public class BeatmapDB {
stmt.setBoolean(44, beatmap.favorite); stmt.setBoolean(44, beatmap.favorite);
stmt.setInt(45, beatmap.playCount); stmt.setInt(45, beatmap.playCount);
stmt.setLong(46, beatmap.lastPlayed); stmt.setLong(46, beatmap.lastPlayed);
stmt.setInt(47, beatmap.localMusicOffset);
} catch (SQLException e) { } catch (SQLException e) {
throw e; throw e;
} catch (Exception e) { } catch (Exception e) {
@ -549,6 +556,7 @@ public class BeatmapDB {
beatmap.favorite = rs.getBoolean(44); beatmap.favorite = rs.getBoolean(44);
beatmap.playCount = rs.getInt(45); beatmap.playCount = rs.getInt(45);
beatmap.lastPlayed = rs.getLong(46); beatmap.lastPlayed = rs.getLong(46);
beatmap.localMusicOffset = rs.getInt(47);
} catch (SQLException e) { } catch (SQLException e) {
throw e; throw e;
} catch (Exception e) { } catch (Exception e) {
@ -694,6 +702,24 @@ public class BeatmapDB {
} }
} }
/**
* Updates the local music offset for a beatmap in the database.
* @param beatmap the beatmap
*/
public static void updateLocalOffset(Beatmap beatmap) {
if (connection == null)
return;
try {
setLocalOffsetStmt.setInt(1, beatmap.localMusicOffset);
setLocalOffsetStmt.setString(2, beatmap.getFile().getParentFile().getName());
setLocalOffsetStmt.setString(3, beatmap.getFile().getName());
setLocalOffsetStmt.executeUpdate();
} catch (SQLException e) {
ErrorHandler.explode(String.format("Failed to update local music offset for beatmap '%s' in database.",
beatmap.toString()), e, ErrorHandler.DEFAULT_OPTIONS);
}
}
/** /**
* Closes the connection to the database. * Closes the connection to the database.
*/ */

View File

@ -265,8 +265,6 @@ public class Game extends ComplexOpsuState {
/** Music position bar coordinates and dimensions (for replay seeking). */ /** Music position bar coordinates and dimensions (for replay seeking). */
private float musicBarX, musicBarY, musicBarWidth, musicBarHeight; private float musicBarX, musicBarY, musicBarWidth, musicBarHeight;
public static int currentMapMusicOffset;
private int mirrorFrom; private int mirrorFrom;
private int mirrorTo; private int mirrorTo;
@ -386,7 +384,7 @@ public class Game extends ComplexOpsuState {
public void render(Graphics g) { public void render(Graphics g) {
int trackPosition = MusicController.getPosition(); int trackPosition = MusicController.getPosition();
if (isLeadIn()) { if (isLeadIn()) {
trackPosition -= leadInTime - currentMapMusicOffset - OPTION_MUSIC_OFFSET.val; trackPosition -= leadInTime - OPTION_MUSIC_OFFSET.val - beatmap.localMusicOffset;
} }
if (pauseTime > -1) // returning from pause screen if (pauseTime > -1) // returning from pause screen
trackPosition = pauseTime; trackPosition = pauseTime;
@ -439,7 +437,7 @@ public class Game extends ComplexOpsuState {
if (GameMod.FLASHLIGHT.isActive()) { if (GameMod.FLASHLIGHT.isActive()) {
// render hit objects offscreen // render hit objects offscreen
Graphics.setCurrent(gOffscreen); Graphics.setCurrent(gOffscreen);
int trackPos = (isLeadIn()) ? (leadInTime - OPTION_MUSIC_OFFSET.val) * -1 : trackPosition; int trackPos = (isLeadIn()) ? (leadInTime - OPTION_MUSIC_OFFSET.val - beatmap.localMusicOffset) * -1 : trackPosition;
drawHitObjects(gOffscreen, trackPos); drawHitObjects(gOffscreen, trackPos);
// restore original graphics context // restore original graphics context
@ -566,8 +564,8 @@ public class Game extends ComplexOpsuState {
Colors.WHITE_FADE.a = oldAlpha; Colors.WHITE_FADE.a = oldAlpha;
} }
if (isLeadIn()) if (isLeadIn()) // render approach circles during song lead-in
trackPosition = (leadInTime - OPTION_MUSIC_OFFSET.val) * -1; // render approach circles during song lead-in trackPosition = (leadInTime - OPTION_MUSIC_OFFSET.val - beatmap.localMusicOffset) * -1;
// countdown // countdown
if (beatmap.countdown > 0) { if (beatmap.countdown > 0) {
@ -1231,14 +1229,13 @@ public class Game extends ComplexOpsuState {
} }
OPTION_DANCE_MIRROR.toggle(); OPTION_DANCE_MIRROR.toggle();
break; break;
case KEY_SUBTRACT:
case KEY_MINUS: case KEY_MINUS:
currentMapMusicOffset += 5; adjustLocalMusicOffset(-5);
barNotifs.send("Current map offset: " + currentMapMusicOffset);
break; break;
} }
if (key == KEY_ADD || c == '+') { if (key == KEY_EQUALS || key == KEY_ADD || c == '+') {
currentMapMusicOffset -= 5; adjustLocalMusicOffset(5);
barNotifs.send("Current map offset: " + currentMapMusicOffset);
} }
return true; return true;
@ -1650,6 +1647,10 @@ public class Game extends ComplexOpsuState {
scoreboardVisible = true; scoreboardVisible = true;
currentScoreboardAlpha = 0f; currentScoreboardAlpha = 0f;
// using local offset?
if (beatmap.localMusicOffset != 0)
barNotifs.send(String.format("Using local beatmap offset (%dms)", beatmap.localMusicOffset));
// needs to play before setting position to resume without lag later // needs to play before setting position to resume without lag later
MusicController.play(false); MusicController.play(false);
MusicController.setPosition(0); MusicController.setPosition(0);
@ -1750,6 +1751,18 @@ public class Game extends ComplexOpsuState {
GameMod.loadModState(previousMods); GameMod.loadModState(previousMods);
} }
/**
* Adjusts the beatmap's local music offset.
* @param sign the sign (multiplier)
*/
public void adjustLocalMusicOffset(int amount) {
int newOffset = beatmap.localMusicOffset + amount;
barNotifs.send(String.format("Local beatmap offset set to %dms", newOffset));
if (beatmap.localMusicOffset != newOffset) {
beatmap.localMusicOffset = newOffset;
BeatmapDB.updateLocalOffset(beatmap);
}
}
public void addMergedSliderPointsToRender(int from, int to) { public void addMergedSliderPointsToRender(int from, int to) {
knorkesliders.addRange(from, to); knorkesliders.addRange(from, to);
} }
@ -1908,9 +1921,6 @@ public class Game extends ComplexOpsuState {
* @param beatmap the beatmap to load * @param beatmap the beatmap to load
*/ */
public void loadBeatmap(Beatmap beatmap) { public void loadBeatmap(Beatmap beatmap) {
if (this.beatmap == null || this.beatmap.beatmapID != beatmap.beatmapID) {
currentMapMusicOffset = 0;
}
this.beatmap = beatmap; this.beatmap = beatmap;
Display.setTitle(String.format("opsu!dance - %s", beatmap.toString())); Display.setTitle(String.format("opsu!dance - %s", beatmap.toString()));
if (beatmap.breaks == null) { if (beatmap.breaks == null) {

View File

@ -117,6 +117,15 @@ public class GamePauseMenu extends BaseOpsuState {
return true; return true;
} }
if (key == KEY_SUBTRACT || key == KEY_MINUS) {
gameState.adjustLocalMusicOffset(-5);
return true;
}
if (key == KEY_EQUALS || key == KEY_ADD || c == '+') {
gameState.adjustLocalMusicOffset(5);
return true;
}
return false; return false;
} }

View File

@ -423,7 +423,7 @@ public class Options {
public static final NumericOption OPTION_EFFECT_VOLUME = new NumericOption("Effects", "VolumeEffect", "Volume of menu and game sounds.", 70, 0, 100); public static final NumericOption OPTION_EFFECT_VOLUME = new NumericOption("Effects", "VolumeEffect", "Volume of menu and game sounds.", 70, 0, 100);
public static final NumericOption OPTION_HITSOUND_VOLUME = new NumericOption("Hit Sounds", "VolumeHitSound", "Volume of hit sounds.", 30, 0, 100); public static final NumericOption OPTION_HITSOUND_VOLUME = new NumericOption("Hit Sounds", "VolumeHitSound", "Volume of hit sounds.", 30, 0, 100);
public static final NumericOption OPTION_MUSIC_OFFSET = new NumericOption("Music Offset", "Offset", "Adjust this value if hit objects are out of sync.", -75, -500, 500) { public static final NumericOption OPTION_MUSIC_OFFSET = new NumericOption("Global Music Offset", "Offset", "Adjust this value if hit objects are out of sync.", -75, -500, 500) {
@Override @Override
public String getValueString () { public String getValueString () {
return String.format("%dms", val); return String.format("%dms", val);