From 7ffda59a033dd3c9a017830a60e3d7e34453bfdc Mon Sep 17 00:00:00 2001 From: EliteAsian Date: Thu, 22 Dec 2022 17:03:27 -0500 Subject: [PATCH] Song delays --- Assets/Script/Game.cs | 13 +++-- Assets/Script/Serialization/AbstractParser.cs | 4 +- Assets/Script/Serialization/MidiParser.cs | 26 ++++++++- Assets/Script/Serialization/SongIni.cs | 55 +++++++++++++++++++ Assets/Script/Serialization/SongIni.cs.meta | 11 ++++ Assets/Script/UI/MainMenu.cs | 7 ++- Assets/Script/UI/Menu.cs | 26 +-------- Assets/Script/UI/SongInfo.cs | 7 ++- Assets/Script/UI/SongInfoComponent.cs | 1 - Assets/Script/Utils/SourceDelays.cs | 14 +++++ Assets/Script/Utils/SourceDelays.cs.meta | 11 ++++ 11 files changed, 137 insertions(+), 38 deletions(-) create mode 100644 Assets/Script/Serialization/SongIni.cs create mode 100644 Assets/Script/Serialization/SongIni.cs.meta create mode 100644 Assets/Script/Utils/SourceDelays.cs create mode 100644 Assets/Script/Utils/SourceDelays.cs.meta diff --git a/Assets/Script/Game.cs b/Assets/Script/Game.cs index 258a208f5..d30465b5a 100644 --- a/Assets/Script/Game.cs +++ b/Assets/Script/Game.cs @@ -6,6 +6,8 @@ using UnityEngine.Networking; using UnityEngine.SceneManagement; using YARG.Serialization; +using YARG.UI; +using YARG.Utils; namespace YARG { public class Game : MonoBehaviour { @@ -15,7 +17,7 @@ public class Game : MonoBehaviour { public static readonly DirectoryInfo SONG_FOLDER = new(@"B:\Clone Hero Alpha\Songs"); public static readonly FileInfo CACHE_FILE = new(Path.Combine(SONG_FOLDER.ToString(), "yarg_cache.json")); - public static DirectoryInfo song = new(@"B:\Clone Hero Alpha\Songs\Jane's Addiction - Been Caught Stealing"); + public static SongInfo song = null; [SerializeField] private GameObject soundAudioPrefab; @@ -44,13 +46,13 @@ private void Awake() { // Song - StartCoroutine(StartSong(song)); + StartCoroutine(StartSong()); } - private IEnumerator StartSong(DirectoryInfo songFolder) { + private IEnumerator StartSong() { // Load audio List audioSources = new(); - foreach (var file in songFolder.GetFiles("*.ogg")) { + foreach (var file in song.folder.GetFiles("*.ogg")) { if (file.Name == "preview.ogg") { continue; } @@ -69,7 +71,8 @@ private IEnumerator StartSong(DirectoryInfo songFolder) { } // Load midi - var parser = new MidiParser(Path.Combine(songFolder.FullName, "notes.mid")); + var parser = new MidiParser(Path.Combine(song.folder.FullName, "notes.mid"), + song.delay + SourceDelays.GetSourceDelay(song.source)); chart = new Chart(); parser.Parse(chart); diff --git a/Assets/Script/Serialization/AbstractParser.cs b/Assets/Script/Serialization/AbstractParser.cs index 0c5c99474..814b25264 100644 --- a/Assets/Script/Serialization/AbstractParser.cs +++ b/Assets/Script/Serialization/AbstractParser.cs @@ -1,9 +1,11 @@ namespace YARG.Serialization { public abstract class AbstractParser { protected string file; + protected float delay; - public AbstractParser(string file) { + public AbstractParser(string file, float delay) { this.file = file; + this.delay = delay; } public abstract void Parse(Chart chart); diff --git a/Assets/Script/Serialization/MidiParser.cs b/Assets/Script/Serialization/MidiParser.cs index ddc2c3be3..0756fb3f8 100644 --- a/Assets/Script/Serialization/MidiParser.cs +++ b/Assets/Script/Serialization/MidiParser.cs @@ -30,7 +30,7 @@ private struct NoteIR { public MidiFile midi; - public MidiParser(string file) : base(file) { + public MidiParser(string file, float delay) : base(file, delay) { midi = MidiFile.Read(file); } @@ -70,13 +70,33 @@ public override void Parse(Chart chart) { } } - // Sort by time (just in case) + // Sort by time (just in case) and add delay + foreach (var part in chart.allParts) { foreach (var difficulty in part) { + if (difficulty == null) { + continue; + } + + // Sort difficulty?.Sort(new Comparison((a, b) => a.time.CompareTo(b.time))); + + // Add delay + foreach (var note in difficulty) { + note.time -= delay; + } + } + } + + if (chart.events != null) { + // Sort + chart.events.Sort(new Comparison((a, b) => a.time.CompareTo(b.time))); + + // Add delay + foreach (var ev in chart.events) { + ev.time -= delay; } } - chart.events?.Sort(new Comparison((a, b) => a.time.CompareTo(b.time))); } private List ParseGuitar(TrackChunk trackChunk, int difficulty) { diff --git a/Assets/Script/Serialization/SongIni.cs b/Assets/Script/Serialization/SongIni.cs new file mode 100644 index 000000000..e0bf74e76 --- /dev/null +++ b/Assets/Script/Serialization/SongIni.cs @@ -0,0 +1,55 @@ +using System; +using System.IO; +using IniParser; +using UnityEngine; +using YARG.UI; + +namespace YARG.Serialization { + public static class SongIni { + public static SongInfo CompleteSongInfo(SongInfo song, FileIniDataParser parser) { + if (song.fetched) { + return song; + } + + var file = new FileInfo(Path.Combine(song.folder.ToString(), "song.ini")); + if (!file.Exists) { + return song; + } + + song.fetched = true; + try { + var data = parser.ReadFile(file.FullName); + + // Set basic info + song.SongName ??= data["song"]["name"]; + song.artistName ??= data["song"]["artist"]; + song.source ??= data["song"]["icon"]; + + // Get song length + if (data["song"].ContainsKey("song_length")) { + int rawLength = int.Parse(data["song"]["song_length"]); + song.songLength = rawLength / 1000f; + } else { + Debug.LogWarning($"No song length found for: {song.folder}"); + } + + // Get song delay (0 if none) + if (data["song"].ContainsKey("delay")) { + int rawDelay = int.Parse(data["song"]["delay"]); + song.delay = rawDelay / 1000f; + } else { + song.delay = 0f; + } + } catch (Exception e) { + song.errored = true; + Debug.LogException(e); + } + + return song; + } + + public static SongInfo CompleteSongInfo(SongInfo song) { + return CompleteSongInfo(song, new FileIniDataParser()); + } + } +} \ No newline at end of file diff --git a/Assets/Script/Serialization/SongIni.cs.meta b/Assets/Script/Serialization/SongIni.cs.meta new file mode 100644 index 000000000..731e91b23 --- /dev/null +++ b/Assets/Script/Serialization/SongIni.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b6e1ce76fe97ffc43826bc090d29ff69 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Script/UI/MainMenu.cs b/Assets/Script/UI/MainMenu.cs index 63a410ca8..cd7f74849 100644 --- a/Assets/Script/UI/MainMenu.cs +++ b/Assets/Script/UI/MainMenu.cs @@ -2,6 +2,7 @@ using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UIElements; +using YARG.Serialization; using YARG.Utils; namespace YARG.UI { @@ -51,7 +52,9 @@ private void OnDisable() { private void SignalRecieved(string signal) { if (signal.StartsWith("DownloadDone,")) { - Game.song = new(Path.Combine(PlayerManager.client.remotePath, signal[13..^0])); + Game.song = SongIni.CompleteSongInfo(new SongInfo( + new(Path.Combine(PlayerManager.client.remotePath, signal[13..^0])) + )); SceneManager.LoadScene(1); } } @@ -111,7 +114,7 @@ private void SetupPreSong() { if (PlayerManager.client != null) { Menu.DownloadSong(chosenSong); } else { - Game.song = chosenSong.folder; + Game.song = chosenSong; SceneManager.LoadScene(1); } return; diff --git a/Assets/Script/UI/Menu.cs b/Assets/Script/UI/Menu.cs index fd9ebedcc..21fe6be4f 100644 --- a/Assets/Script/UI/Menu.cs +++ b/Assets/Script/UI/Menu.cs @@ -8,6 +8,7 @@ using TMPro; using UnityEngine; using UnityEngine.UI; +using YARG.Serialization; namespace YARG.UI { public class Menu : MonoBehaviour { @@ -94,30 +95,7 @@ private static void FetchSongInfo() { // Fetch song info manually var parser = new FileIniDataParser(); foreach (var song in songs) { - if (song.fetched) { - return; - } - - var file = new FileInfo(Path.Combine(song.folder.ToString(), "song.ini")); - if (!file.Exists) { - return; - } - - song.fetched = true; - try { - var data = parser.ReadFile(file.FullName); - - // Set basic info - song.SongName ??= data["song"]["name"]; - song.artistName ??= data["song"]["artist"]; - - // Get song length - int rawLength = int.Parse(data["song"]["song_length"]); - song.songLength = rawLength / 1000f; - } catch (Exception e) { - song.errored = true; - Debug.LogException(e); - } + SongIni.CompleteSongInfo(song, parser); } // Create cache diff --git a/Assets/Script/UI/SongInfo.cs b/Assets/Script/UI/SongInfo.cs index 354fdf22b..daeae89a9 100644 --- a/Assets/Script/UI/SongInfo.cs +++ b/Assets/Script/UI/SongInfo.cs @@ -5,13 +5,14 @@ namespace YARG.UI { [JsonObject(MemberSerialization.Fields)] public class SongInfo { - [JsonConverter(typeof(DirectoryInfoConverter))] - public DirectoryInfo folder; [JsonIgnore] public bool fetched; [JsonIgnore] public bool errored; + [JsonConverter(typeof(DirectoryInfoConverter))] + public DirectoryInfo folder; + [field: JsonProperty("bassPedal2xExpertPlus")] public bool BassPedal2xExpertPlus { private set; @@ -46,8 +47,10 @@ public string SongName { public string SongNameNoParen => SongName.Replace("(", "").Replace(")", ""); public string artistName; + public string source; public float? songLength; + public float delay; public SongInfo(DirectoryInfo folder) { this.folder = folder; diff --git a/Assets/Script/UI/SongInfoComponent.cs b/Assets/Script/UI/SongInfoComponent.cs index aa04052d8..7838e2e13 100644 --- a/Assets/Script/UI/SongInfoComponent.cs +++ b/Assets/Script/UI/SongInfoComponent.cs @@ -1,6 +1,5 @@ using TMPro; using UnityEngine; -using UnityEngine.SceneManagement; namespace YARG.UI { public class SongInfoComponent : MonoBehaviour { diff --git a/Assets/Script/Utils/SourceDelays.cs b/Assets/Script/Utils/SourceDelays.cs new file mode 100644 index 000000000..36387dec6 --- /dev/null +++ b/Assets/Script/Utils/SourceDelays.cs @@ -0,0 +1,14 @@ +namespace YARG.Utils { + public static class SourceDelays { + public static float GetSourceDelay(string source) { + // Hardcode a delay for certain games (such as RB1). + // There may be a chance that I am reading the MIDI or something + // incorrectly. This is the fix for now, and it seems to work for + // the most part. + return source switch { + "rb1" or "rb1dlc" => 0.15f, + _ => 0f + }; + } + } +} \ No newline at end of file diff --git a/Assets/Script/Utils/SourceDelays.cs.meta b/Assets/Script/Utils/SourceDelays.cs.meta new file mode 100644 index 000000000..ee26efae7 --- /dev/null +++ b/Assets/Script/Utils/SourceDelays.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8b071f0dd4afc7142a8514b68640ad39 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: