diff --git a/Platform/Apple/tools/jace/.idea/.gitignore b/Platform/Apple/tools/jace/.idea/.gitignore new file mode 100644 index 00000000..73f69e09 --- /dev/null +++ b/Platform/Apple/tools/jace/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/Platform/Apple/tools/jace/lawlesslegends.iml b/Platform/Apple/tools/jace/lawlesslegends.iml new file mode 100644 index 00000000..1f4a2c9c --- /dev/null +++ b/Platform/Apple/tools/jace/lawlesslegends.iml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Platform/Apple/tools/jace/src/main/java/jace/lawless/LawlessHacks.java b/Platform/Apple/tools/jace/src/main/java/jace/lawless/LawlessHacks.java index 3c047b8a..e172ef15 100644 --- a/Platform/Apple/tools/jace/src/main/java/jace/lawless/LawlessHacks.java +++ b/Platform/Apple/tools/jace/src/main/java/jace/lawless/LawlessHacks.java @@ -14,10 +14,14 @@ import java.io.InputStreamReader; import java.net.URISyntaxException; import java.net.URL; import java.util.HashMap; +import java.util.HashSet; import java.util.Locale; import java.util.Map; +import java.util.Optional; +import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; +import javafx.util.Duration; /** * Hacks that affect lawless legends gameplay @@ -32,7 +36,7 @@ public class LawlessHacks extends Cheats { public LawlessHacks(Computer computer) { super(computer); readScores(); - currentScore = SCORE_ORCHESTRAL; + currentScore = SCORE_CHIPTUNE; } @Override @@ -76,8 +80,8 @@ public class LawlessHacks extends Cheats { public static final String SCORE_NONE = "none"; public static final String SCORE_COMMON = "common"; - public static final String SCORE_ORCHESTRAL = "orchestral"; - public static final String SCORE_CHIPTUNE = "chiptune"; + public static final String SCORE_ORCHESTRAL = "8-bit orchestral samples"; + public static final String SCORE_CHIPTUNE = "8-bit chipmusic"; private static int currentSong; private static boolean repeatSong = false; @@ -100,14 +104,14 @@ public class LawlessHacks extends Cheats { } } else if (isMusic) { System.out.println("Play music "+track); - playMusic(track); + playMusic(track, false); } else { System.out.println("Play sfx "+track); playSfx(track); } } - - private Media getAudioTrack(int number) { + + private String getSongName(int number) { Map score = scores.get(currentScore); if (score == null) { return null; @@ -120,6 +124,11 @@ public class LawlessHacks extends Cheats { } filename = score.get(number); } + return filename; + } + + private Media getAudioTrack(int number) { + String filename = getSongName(number); String pathStr = "jace/data/sound/" + filename; // System.out.println("looking in "+pathStr); URL path = getClass().getClassLoader().getResource(pathStr); @@ -134,11 +143,11 @@ public class LawlessHacks extends Cheats { } } - private void playMusic(int track) { - if (currentSong != track) { - fadeOutSong(() -> startNewSong(track)); + private void playMusic(int track, boolean switchScores) { + if (currentSong != track || switchScores) { + fadeOutSong(() -> startNewSong(track, switchScores)); } else { - new Thread(() -> startNewSong(track)).start(); + new Thread(() -> startNewSong(track, false)).start(); } currentSong = track; } @@ -154,11 +163,22 @@ public class LawlessHacks extends Cheats { } playbackEffect = null; } + + private Optional getCurrentTime() { + if (currentSongPlayer == null) { + return Optional.empty(); + } else if (currentSongPlayer.getCurrentTime() == null) { + return Optional.empty(); + } else { + return Optional.of(currentSongPlayer.getCurrentTime().toMillis()); + } + } private void fadeOutSong(Runnable nextAction) { stopSongEffect(); MediaPlayer player = currentSongPlayer; if (player != null) { + getCurrentTime().ifPresent(val -> lastTime.put(currentSong, val + 1500)); playbackEffect = new Thread(() -> { DoubleProperty volume = player.volumeProperty(); while (playbackEffect == Thread.currentThread() && volume.get() > 0.0) { @@ -207,23 +227,29 @@ public class LawlessHacks extends Cheats { } double FADE_AMT = 0.05; // 5% per interval, or 20 stops between 0% and 100% - int FADE_SPEED = 100; // 100ms per 5%, or 2 second duration +// int FADE_SPEED = 100; // 100ms per 5%, or 2 second duration + int FADE_SPEED = 75; // 75ms per 5%, or 1.5 second duration - private void startNewSong(int track) { + private void startNewSong(int track, boolean switchScores) { if (!isMusicEnabled()) { return; } MediaPlayer player; - if (track != currentSong || !isPlayingMusic()) { + if (track != currentSong || !isPlayingMusic() || switchScores) { // If the same song is already playing don't restart it Media song = getAudioTrack(track); if (song == null) { - System.out.println("Unable to start song " + track + "; File not found"); + System.out.println("Unable to start song " + track + "; File " + getSongName(track) + " not found"); return; } player = new MediaPlayer(song); player.setCycleCount(repeatSong ? MediaPlayer.INDEFINITE : 1); player.setVolume(0.0); + if (autoResume.contains(track) || switchScores) { + double time = lastTime.getOrDefault(track, 0.0); + System.out.println("Auto-resume from time " + time); + player.setStartTime(Duration.millis(time)); + } player.play(); } else { // But if the same song was already playing but possibly fading out @@ -272,10 +298,7 @@ public class LawlessHacks extends Cheats { stopMusic(); currentSong = -1; } else if ((currentSongPlayer != null || wasStoppedPreviously) && currentSong > 0) { - stopSongEffect(); - int currentSongTemp = currentSong; - currentSong = Integer.MAX_VALUE; - startNewSong(currentSongTemp); + playMusic(currentSong, true); } } @@ -284,9 +307,11 @@ public class LawlessHacks extends Cheats { } Pattern COMMENT = Pattern.compile("\\s*[-#;']+.*"); - Pattern LABEL = Pattern.compile("[A-Za-z\\s\\-_]+"); + Pattern LABEL = Pattern.compile("(8-)?[A-Za-z\\s\\-_]+"); Pattern ENTRY = Pattern.compile("([0-9]+)\\s+(.*)"); - private Map> scores = new HashMap<>(); + private final Map> scores = new HashMap<>(); + private final Set autoResume = new HashSet<>(); + private final Map lastTime = new HashMap<>(); private void readScores() { InputStream data = getClass().getClassLoader().getResourceAsStream("jace/data/sound/scores.txt"); readScores(data); @@ -295,6 +320,11 @@ public class LawlessHacks extends Cheats { private void readScores(InputStream data) { BufferedReader reader = new BufferedReader(new InputStreamReader(data)); reader.lines().forEach(line -> { + boolean useAutoResume = false; + if (line.indexOf('*') > 0) { + useAutoResume = true; + line = line.replace("*", ""); + } if (COMMENT.matcher(line).matches() || line.trim().isEmpty()) { // System.out.println("Ignoring: "+line); return; @@ -308,6 +338,9 @@ public class LawlessHacks extends Cheats { int num = Integer.parseInt(m.group(1)); String file = m.group(2); scores.get(currentScore).put(num, file); + if (useAutoResume) { + autoResume.add(num); + } // System.out.println("Score: " + currentScore + "; Song: " + num + "; " + file); } else { // System.out.println("Couldn't parse: " + line); diff --git a/Platform/Apple/tools/jace/src/main/resources/fxml/JaceUI.fxml b/Platform/Apple/tools/jace/src/main/resources/fxml/JaceUI.fxml index fc33fb70..0fba4b16 100644 --- a/Platform/Apple/tools/jace/src/main/resources/fxml/JaceUI.fxml +++ b/Platform/Apple/tools/jace/src/main/resources/fxml/JaceUI.fxml @@ -83,13 +83,13 @@ - - + + - +