Restores drainRate
Single file read md5 pitch change synctime
This commit is contained in:
@@ -296,6 +296,10 @@ public class GameData {
|
|||||||
/** The difficulty multiplier used in the score formula. */
|
/** The difficulty multiplier used in the score formula. */
|
||||||
private int difficultyMultiplier = 2;
|
private int difficultyMultiplier = 2;
|
||||||
|
|
||||||
|
/** Beatmap HPDrainRate value. (0:easy ~ 10:hard) */
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private float drainRate = 5f;
|
||||||
|
|
||||||
/** Default text symbol images. */
|
/** Default text symbol images. */
|
||||||
private Image[] defaultSymbols;
|
private Image[] defaultSymbols;
|
||||||
|
|
||||||
@@ -371,6 +375,7 @@ public class GameData {
|
|||||||
health = 100f;
|
health = 100f;
|
||||||
healthDisplay = 100f;
|
healthDisplay = 100f;
|
||||||
hitResultCount = new int[HIT_MAX];
|
hitResultCount = new int[HIT_MAX];
|
||||||
|
drainRate = 5f;
|
||||||
if (hitResultList != null) {
|
if (hitResultList != null) {
|
||||||
for (HitObjectResult hitResult : hitResultList) {
|
for (HitObjectResult hitResult : hitResultList) {
|
||||||
if (hitResult.curve != null)
|
if (hitResult.curve != null)
|
||||||
@@ -461,6 +466,12 @@ public class GameData {
|
|||||||
*/
|
*/
|
||||||
public Image getScoreSymbolImage(char c) { return scoreSymbols.get(c); }
|
public Image getScoreSymbolImage(char c) { return scoreSymbols.get(c); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the health drain rate.
|
||||||
|
* @param drainRate the new drain rate [0-10]
|
||||||
|
*/
|
||||||
|
public void setDrainRate(float drainRate) { this.drainRate = drainRate; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the array of hit result offsets.
|
* Sets the array of hit result offsets.
|
||||||
*/
|
*/
|
||||||
@@ -1423,7 +1434,7 @@ public class GameData {
|
|||||||
replay = new Replay();
|
replay = new Replay();
|
||||||
replay.mode = Beatmap.MODE_OSU;
|
replay.mode = Beatmap.MODE_OSU;
|
||||||
replay.version = Updater.get().getBuildDate();
|
replay.version = Updater.get().getBuildDate();
|
||||||
replay.beatmapHash = (beatmap == null) ? "" : Utils.getMD5(beatmap.getFile());
|
replay.beatmapHash = (beatmap == null) ? "" : beatmap.md5Hash;//Utils.getMD5(beatmap.getFile());
|
||||||
replay.playerName = ""; // TODO
|
replay.playerName = ""; // TODO
|
||||||
replay.replayHash = Long.toString(System.currentTimeMillis()); // TODO
|
replay.replayHash = Long.toString(System.currentTimeMillis()); // TODO
|
||||||
replay.hit300 = (short) hitResultCount[HIT_300];
|
replay.hit300 = (short) hitResultCount[HIT_300];
|
||||||
|
|||||||
91
src/itdelatrisu/opsu/MD5InputStreamWrapper.java
Normal file
91
src/itdelatrisu/opsu/MD5InputStreamWrapper.java
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
package itdelatrisu.opsu;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
|
||||||
|
public class MD5InputStreamWrapper extends InputStream {
|
||||||
|
|
||||||
|
InputStream in;
|
||||||
|
private boolean eof; // End Of File
|
||||||
|
MessageDigest md;
|
||||||
|
public MD5InputStreamWrapper(InputStream in) throws NoSuchAlgorithmException {
|
||||||
|
this.in = in;
|
||||||
|
md = MessageDigest.getInstance("MD5");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read() throws IOException {
|
||||||
|
int readed = in.read();
|
||||||
|
if(readed>=0)
|
||||||
|
md.update((byte) readed);
|
||||||
|
else
|
||||||
|
eof=true;
|
||||||
|
return readed;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int available() throws IOException {
|
||||||
|
return in.available();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
in.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void mark(int readlimit) {
|
||||||
|
in.mark(readlimit);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean markSupported() {
|
||||||
|
return in.markSupported();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read(byte[] b, int off, int len) throws IOException {
|
||||||
|
int readed = in.read(b, off, len);
|
||||||
|
if(readed>=0)
|
||||||
|
md.update(b, off, readed);
|
||||||
|
else
|
||||||
|
eof=true;
|
||||||
|
|
||||||
|
return readed;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read(byte[] b) throws IOException {
|
||||||
|
return read(b, 0 ,b.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void reset() throws IOException {
|
||||||
|
throw new RuntimeException("MD5 stream not resetable");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long skip(long n) throws IOException {
|
||||||
|
throw new RuntimeException("MD5 stream not skipable");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMD5() throws IOException {
|
||||||
|
byte[] buf = null;
|
||||||
|
if(!eof)
|
||||||
|
buf = new byte[0x1000];
|
||||||
|
while(!eof){
|
||||||
|
read(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] md5byte = md.digest();
|
||||||
|
StringBuilder result = new StringBuilder();
|
||||||
|
for (byte b : md5byte)
|
||||||
|
result.append(String.format("%02x", b));
|
||||||
|
//System.out.println("MD5 stream md5 " + result.toString());
|
||||||
|
return result.toString();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -19,16 +19,20 @@
|
|||||||
package itdelatrisu.opsu.beatmap;
|
package itdelatrisu.opsu.beatmap;
|
||||||
|
|
||||||
import itdelatrisu.opsu.ErrorHandler;
|
import itdelatrisu.opsu.ErrorHandler;
|
||||||
|
import itdelatrisu.opsu.MD5InputStreamWrapper;
|
||||||
import itdelatrisu.opsu.Utils;
|
import itdelatrisu.opsu.Utils;
|
||||||
import itdelatrisu.opsu.db.BeatmapDB;
|
import itdelatrisu.opsu.db.BeatmapDB;
|
||||||
|
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileReader;
|
import java.io.FileReader;
|
||||||
import java.io.FilenameFilter;
|
import java.io.FilenameFilter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -205,7 +209,15 @@ public class BeatmapParser {
|
|||||||
Beatmap beatmap = new Beatmap(file);
|
Beatmap beatmap = new Beatmap(file);
|
||||||
beatmap.timingPoints = new ArrayList<TimingPoint>();
|
beatmap.timingPoints = new ArrayList<TimingPoint>();
|
||||||
|
|
||||||
try (BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"))) {
|
try (InputStream inFileStream = new BufferedInputStream(new FileInputStream(file));){
|
||||||
|
MD5InputStreamWrapper md5stream = null;
|
||||||
|
try {
|
||||||
|
md5stream = new MD5InputStreamWrapper(inFileStream);
|
||||||
|
} catch (NoSuchAlgorithmException e1) {
|
||||||
|
ErrorHandler.error("Failed to get MD5 hash stream.", e1, true);
|
||||||
|
}
|
||||||
|
BufferedReader in = new BufferedReader(new InputStreamReader(md5stream!=null?md5stream:inFileStream, "UTF-8"));
|
||||||
|
|
||||||
String line = in.readLine();
|
String line = in.readLine();
|
||||||
String tokens[] = null;
|
String tokens[] = null;
|
||||||
while (line != null) {
|
while (line != null) {
|
||||||
@@ -578,6 +590,8 @@ public class BeatmapParser {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (md5stream != null)
|
||||||
|
beatmap.md5Hash = md5stream.getMD5();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
ErrorHandler.error(String.format("Failed to read file '%s'.", file.getAbsolutePath()), e, false);
|
ErrorHandler.error(String.format("Failed to read file '%s'.", file.getAbsolutePath()), e, false);
|
||||||
}
|
}
|
||||||
@@ -590,8 +604,6 @@ public class BeatmapParser {
|
|||||||
if (parseObjects)
|
if (parseObjects)
|
||||||
parseHitObjects(beatmap);
|
parseHitObjects(beatmap);
|
||||||
|
|
||||||
beatmap.md5Hash = Utils.getMD5(file);
|
|
||||||
|
|
||||||
return beatmap;
|
return beatmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -132,10 +132,8 @@ public class Circle implements GameObject {
|
|||||||
result = GameData.HIT_100;
|
result = GameData.HIT_100;
|
||||||
else if (timeDiff <= hitResultOffset[GameData.HIT_50])
|
else if (timeDiff <= hitResultOffset[GameData.HIT_50])
|
||||||
result = GameData.HIT_50;
|
result = GameData.HIT_50;
|
||||||
else if (timeDiff <= hitResultOffset[GameData.HIT_MISS]){
|
else if (timeDiff <= hitResultOffset[GameData.HIT_MISS])
|
||||||
result = GameData.HIT_MISS;
|
result = GameData.HIT_MISS;
|
||||||
System.out.println(timeDiff);
|
|
||||||
}
|
|
||||||
//else not a hit
|
//else not a hit
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -227,6 +227,8 @@ public class Game extends BasicGameState {
|
|||||||
|
|
||||||
private int height;
|
private int height;
|
||||||
|
|
||||||
|
private boolean seeking;
|
||||||
|
|
||||||
public Game(int state) {
|
public Game(int state) {
|
||||||
this.state = state;
|
this.state = state;
|
||||||
}
|
}
|
||||||
@@ -615,7 +617,7 @@ public class Game extends BasicGameState {
|
|||||||
updateGame(replayX, replayY, delta, MusicController.getPosition(), lastKeysPressed);
|
updateGame(replayX, replayY, delta, MusicController.getPosition(), lastKeysPressed);
|
||||||
|
|
||||||
//TODO probably should to disable sounds then reseek to the new position
|
//TODO probably should to disable sounds then reseek to the new position
|
||||||
if(replayIndex-1 >= 1 && replayIndex < replay.frames.length && trackPosition < replay.frames[replayIndex-1].getTime()){
|
if(seeking && replayIndex-1 >= 1 && replayIndex < replay.frames.length && trackPosition < replay.frames[replayIndex-1].getTime()){
|
||||||
replayIndex = 0;
|
replayIndex = 0;
|
||||||
while(objectIndex>=0){
|
while(objectIndex>=0){
|
||||||
gameObjects[objectIndex].reset();
|
gameObjects[objectIndex].reset();
|
||||||
@@ -633,6 +635,7 @@ public class Game extends BasicGameState {
|
|||||||
timingPointIndex++;
|
timingPointIndex++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
seeking = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// update and run replay frames
|
// update and run replay frames
|
||||||
@@ -925,6 +928,7 @@ public class Game extends BasicGameState {
|
|||||||
if(!GameMod.AUTO.isActive() && y < 50){
|
if(!GameMod.AUTO.isActive() && y < 50){
|
||||||
float pos = (float)x / width * beatmap.endTime;
|
float pos = (float)x / width * beatmap.endTime;
|
||||||
MusicController.setPosition((int)pos);
|
MusicController.setPosition((int)pos);
|
||||||
|
seeking = true;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1074,6 +1078,8 @@ public class Game extends BasicGameState {
|
|||||||
retries = 0;
|
retries = 0;
|
||||||
|
|
||||||
gameObjects = new GameObject[beatmap.objects.length];
|
gameObjects = new GameObject[beatmap.objects.length];
|
||||||
|
playbackSpeed = PlaybackSpeed.NORMAL;
|
||||||
|
|
||||||
// reset game data
|
// reset game data
|
||||||
resetGameData();
|
resetGameData();
|
||||||
|
|
||||||
@@ -1332,7 +1338,6 @@ public class Game extends BasicGameState {
|
|||||||
autoMouseY = 0;
|
autoMouseY = 0;
|
||||||
autoMousePressed = false;
|
autoMousePressed = false;
|
||||||
flashlightRadius = container.getHeight() * 2 / 3;
|
flashlightRadius = container.getHeight() * 2 / 3;
|
||||||
playbackSpeed = PlaybackSpeed.NORMAL;
|
|
||||||
|
|
||||||
System.gc();
|
System.gc();
|
||||||
}
|
}
|
||||||
@@ -1402,7 +1407,6 @@ public class Game extends BasicGameState {
|
|||||||
float circleSize = Math.min(beatmap.circleSize * multiplier, 10f);
|
float circleSize = Math.min(beatmap.circleSize * multiplier, 10f);
|
||||||
float approachRate = Math.min(beatmap.approachRate * multiplier, 10f);
|
float approachRate = Math.min(beatmap.approachRate * multiplier, 10f);
|
||||||
float overallDifficulty = Math.min(beatmap.overallDifficulty * multiplier, 10f);
|
float overallDifficulty = Math.min(beatmap.overallDifficulty * multiplier, 10f);
|
||||||
//TODO never actually used, everything seems to be using GameData.HP_DRAIN_MULTIPLIER
|
|
||||||
float HPDrainRate = Math.min(beatmap.HPDrainRate * multiplier, 10f);
|
float HPDrainRate = Math.min(beatmap.HPDrainRate * multiplier, 10f);
|
||||||
|
|
||||||
// fixed difficulty overrides
|
// fixed difficulty overrides
|
||||||
@@ -1449,6 +1453,9 @@ public class Game extends BasicGameState {
|
|||||||
data.setHitResultOffset(hitResultOffset);
|
data.setHitResultOffset(hitResultOffset);
|
||||||
//*/
|
//*/
|
||||||
|
|
||||||
|
// HPDrainRate (health change)
|
||||||
|
data.setDrainRate(HPDrainRate);
|
||||||
|
|
||||||
// difficulty multiplier (scoring)
|
// difficulty multiplier (scoring)
|
||||||
data.calculateDifficultyMultiplier(beatmap.HPDrainRate, beatmap.circleSize, beatmap.overallDifficulty);
|
data.calculateDifficultyMultiplier(beatmap.HPDrainRate, beatmap.circleSize, beatmap.overallDifficulty);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ import org.lwjgl.openal.OpenALException;
|
|||||||
import org.newdawn.slick.util.Log;
|
import org.newdawn.slick.util.Log;
|
||||||
import org.newdawn.slick.util.ResourceLoader;
|
import org.newdawn.slick.util.ResourceLoader;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A generic tool to work on a supplied stream, pulling out PCM data and buffered it to OpenAL
|
* A generic tool to work on a supplied stream, pulling out PCM data and buffered it to OpenAL
|
||||||
* as required.
|
* as required.
|
||||||
@@ -224,6 +225,7 @@ public class OpenALStreamPlayer {
|
|||||||
*/
|
*/
|
||||||
public void setup(float pitch) {
|
public void setup(float pitch) {
|
||||||
this.pitch = pitch;
|
this.pitch = pitch;
|
||||||
|
syncPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -354,7 +356,7 @@ public class OpenALStreamPlayer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
playedPos = streamPos;
|
playedPos = streamPos;
|
||||||
syncStartTime = getTime() - playedPos * 1000 / sampleSize / sampleRate;
|
syncStartTime = (long) (getTime() - (playedPos * 1000 / sampleSize / sampleRate)/pitch);
|
||||||
|
|
||||||
startPlayback();
|
startPlayback();
|
||||||
|
|
||||||
@@ -403,24 +405,34 @@ public class OpenALStreamPlayer {
|
|||||||
float thisPosition = getALPosition();
|
float thisPosition = getALPosition();
|
||||||
long thisTime = getTime();
|
long thisTime = getTime();
|
||||||
float dxPosition = thisPosition - lastUpdatePosition;
|
float dxPosition = thisPosition - lastUpdatePosition;
|
||||||
long dxTime = thisTime - syncStartTime;
|
float dxTime = (thisTime - syncStartTime) * pitch;
|
||||||
|
|
||||||
// hard reset
|
// hard reset
|
||||||
if (Math.abs(thisPosition - dxTime / 1000f) > 1 / 2f) {
|
if (Math.abs(thisPosition - dxTime / 1000f) > 1 / 2f) {
|
||||||
syncStartTime = thisTime - ((long) (thisPosition * 1000));
|
//System.out.println("Time HARD Reset"+" "+thisPosition+" "+(dxTime / 1000f));
|
||||||
dxTime = thisTime - syncStartTime;
|
syncPosition();
|
||||||
|
dxTime = (thisTime - syncStartTime) * pitch;
|
||||||
avgDiff = 0;
|
avgDiff = 0;
|
||||||
}
|
}
|
||||||
if ((int) (dxPosition * 1000) != 0) { // lastPosition != thisPosition
|
if ((int) (dxPosition * 1000) != 0) { // lastPosition != thisPosition
|
||||||
float diff = thisPosition * 1000 - (dxTime);
|
float diff = thisPosition * 1000 - (dxTime);
|
||||||
|
|
||||||
avgDiff = (diff + avgDiff * 9) / 10;
|
avgDiff = (diff + avgDiff * 9) / 10;
|
||||||
syncStartTime -= (int) (avgDiff/2);
|
if(Math.abs(avgDiff) >= 1){
|
||||||
dxTime = thisTime - syncStartTime;
|
syncStartTime -= (int)(avgDiff);
|
||||||
|
avgDiff -= (int)(avgDiff);
|
||||||
|
dxTime = (thisTime - syncStartTime) * pitch;
|
||||||
|
}
|
||||||
lastUpdatePosition = thisPosition;
|
lastUpdatePosition = thisPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return dxTime / 1000f;
|
return dxTime / 1000f;
|
||||||
}
|
}
|
||||||
|
private void syncPosition(){
|
||||||
|
syncStartTime = getTime() - (long) ( getALPosition() * 1000 / pitch);
|
||||||
|
avgDiff = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Processes a track pause.
|
* Processes a track pause.
|
||||||
|
|||||||
@@ -536,6 +536,7 @@ public class SoundStore {
|
|||||||
*/
|
*/
|
||||||
public void setMusicPitch(float pitch) {
|
public void setMusicPitch(float pitch) {
|
||||||
if (soundWorks) {
|
if (soundWorks) {
|
||||||
|
stream.setup(pitch);
|
||||||
AL10.alSourcef(sources.get(0), AL10.AL_PITCH, pitch);
|
AL10.alSourcef(sources.get(0), AL10.AL_PITCH, pitch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user