diff --git a/YARG.Core/Chart/Events/ChartEventExtensions.cs b/YARG.Core/Chart/Events/ChartEventExtensions.cs index 1d5b0723f..edc3f0b5c 100644 --- a/YARG.Core/Chart/Events/ChartEventExtensions.cs +++ b/YARG.Core/Chart/Events/ChartEventExtensions.cs @@ -84,7 +84,7 @@ public static uint GetLastTick(this IList events) return chartEvent.TickEnd; } - public static TEvent GetPrevious(this IList events, double time) + public static TEvent? GetPrevious(this IList events, double time) where TEvent : ChartEvent { int index = GetIndexOfPrevious(events, time); @@ -94,7 +94,7 @@ public static TEvent GetPrevious(this IList events, double time) return events[index]; } - public static TEvent GetPrevious(this IList events, uint tick) + public static TEvent? GetPrevious(this IList events, uint tick) where TEvent : ChartEvent { int index = GetIndexOfPrevious(events, tick); @@ -104,7 +104,7 @@ public static TEvent GetPrevious(this IList events, uint tick) return events[index]; } - public static TEvent GetNext(this IList events, double time) + public static TEvent? GetNext(this IList events, double time) where TEvent : ChartEvent { int index = GetIndexOfNext(events, time); @@ -114,7 +114,7 @@ public static TEvent GetNext(this IList events, double time) return events[index]; } - public static TEvent GetNext(this IList events, uint tick) + public static TEvent? GetNext(this IList events, uint tick) where TEvent : ChartEvent { int index = GetIndexOfNext(events, tick); @@ -234,7 +234,7 @@ public static bool GetEventRange(this IList events, uint startTi return true; } - public static TEvent FindClosestEvent(this IList events, double time) + public static TEvent? FindClosestEvent(this IList events, double time) where TEvent : ChartEvent { return events.BinarySearch(time, Compare); @@ -250,7 +250,7 @@ static int Compare(TEvent currentEvent, double targetTime) } } - public static TEvent FindClosestEvent(this IList events, uint tick) + public static TEvent? FindClosestEvent(this IList events, uint tick) where TEvent : ChartEvent { return events.BinarySearch(tick, Compare); diff --git a/YARG.Core/Chart/Loaders/ISongLoader.cs b/YARG.Core/Chart/Loaders/ISongLoader.cs index bc0b1915c..d9949d631 100644 --- a/YARG.Core/Chart/Loaders/ISongLoader.cs +++ b/YARG.Core/Chart/Loaders/ISongLoader.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using Melanchall.DryWetMidi.Core; namespace YARG.Core.Chart { @@ -8,10 +7,6 @@ namespace YARG.Core.Chart /// internal interface ISongLoader { - void LoadSong(ParseSettings settings, string filePath); - void LoadMidi(ParseSettings settings, MidiFile midi); - void LoadDotChart(ParseSettings settings, string chartText); - List LoadGlobalEvents(); SyncTrack LoadSyncTrack(); VenueTrack LoadVenueTrack(); diff --git a/YARG.Core/Chart/Loaders/MoonSong/MoonSongLoader.Venue.cs b/YARG.Core/Chart/Loaders/MoonSong/MoonSongLoader.Venue.cs index 16730d289..8520c1c6e 100644 --- a/YARG.Core/Chart/Loaders/MoonSong/MoonSongLoader.Venue.cs +++ b/YARG.Core/Chart/Loaders/MoonSong/MoonSongLoader.Venue.cs @@ -117,8 +117,8 @@ public VenueTrack LoadVenueTrack() var otherEvents = new List(venueCount / 20); // For merging spotlights/singalongs into a single event - MoonVenueEvent spotlightCurrentEvent = null; - MoonVenueEvent singalongCurrentEvent = null; + MoonVenueEvent? spotlightCurrentEvent = null; + MoonVenueEvent? singalongCurrentEvent = null; var spotlightPerformers = Performer.None; var singalongPerformers = Performer.None; @@ -192,7 +192,7 @@ public VenueTrack LoadVenueTrack() } private void HandlePerformerEvent(List events, PerformerEventType type, MoonVenueEvent moonEvent, - ref MoonVenueEvent currentEvent, ref Performer performers) + ref MoonVenueEvent? currentEvent, ref Performer performers) { // First event if (currentEvent == null) diff --git a/YARG.Core/Chart/Loaders/MoonSong/MoonSongLoader.Vocals.cs b/YARG.Core/Chart/Loaders/MoonSong/MoonSongLoader.Vocals.cs index 12b579d91..ac63db397 100644 --- a/YARG.Core/Chart/Loaders/MoonSong/MoonSongLoader.Vocals.cs +++ b/YARG.Core/Chart/Loaders/MoonSong/MoonSongLoader.Vocals.cs @@ -117,7 +117,7 @@ private List GetVocalsPhrases(MoonChart moonChart, int harmonyPart // Go through each note and lyric in the phrase var notes = new List(); var lyrics = new List(); - VocalNote previousNote = null; + VocalNote? previousNote = null; while (moonNoteIndex < moonChart.notes.Count) { var moonNote = moonChart.notes[moonNoteIndex]; diff --git a/YARG.Core/Chart/Loaders/MoonSong/MoonSongLoader.cs b/YARG.Core/Chart/Loaders/MoonSong/MoonSongLoader.cs index 6e0d24b4d..c768de88b 100644 --- a/YARG.Core/Chart/Loaders/MoonSong/MoonSongLoader.cs +++ b/YARG.Core/Chart/Loaders/MoonSong/MoonSongLoader.cs @@ -26,7 +26,16 @@ private delegate TNote CreateNoteDelegate(MoonNote moonNote, CurrentPhras private Instrument _currentInstrument; private Difficulty _currentDifficulty; - public void LoadSong(ParseSettings settings, string filePath) + private MoonSongLoader(MoonSong song, ParseSettings settings) + { + if (settings.NoteSnapThreshold < 0) + settings.NoteSnapThreshold = 0; + + _moonSong = song; + _settings = settings; + } + + public static MoonSongLoader LoadSong(ParseSettings settings, string filePath) { var song = Path.GetExtension(filePath).ToLower() switch { @@ -35,28 +44,19 @@ public void LoadSong(ParseSettings settings, string filePath) _ => throw new ArgumentException($"Unrecognized file extension for chart path '{filePath}'!", nameof(filePath)) }; - Initialize(song, settings); + return new(song, settings); } - public void LoadMidi(ParseSettings settings, MidiFile midi) + public static MoonSongLoader LoadMidi(ParseSettings settings, MidiFile midi) { var song = MidReader.ReadMidi(settings, midi); - Initialize(song, settings); + return new(song, settings); } - public void LoadDotChart(ParseSettings settings, string chartText) + public static MoonSongLoader LoadDotChart(ParseSettings settings, string chartText) { var song = ChartReader.ReadFromText(settings, chartText); - Initialize(song, settings); - } - - private void Initialize(MoonSong song, ParseSettings settings) - { - if (settings.NoteSnapThreshold < 0) - settings.NoteSnapThreshold = 0; - - _moonSong = song; - _settings = settings; + return new(song, settings); } public List LoadGlobalEvents() @@ -125,7 +125,7 @@ public SyncTrack LoadSyncTrack() } private InstrumentDifficulty LoadDifficulty(Instrument instrument, Difficulty difficulty, - CreateNoteDelegate createNote, ProcessTextDelegate processText = null) + CreateNoteDelegate createNote, ProcessTextDelegate? processText = null) where TNote : Note { _currentInstrument = instrument; @@ -139,7 +139,7 @@ private InstrumentDifficulty LoadDifficulty(Instrument instrument, } private List GetNotes(MoonChart moonChart, Difficulty difficulty, - CreateNoteDelegate createNote, ProcessTextDelegate processText = null) + CreateNoteDelegate createNote, ProcessTextDelegate? processText = null) where TNote : Note { var notes = new List(moonChart.notes.Count); diff --git a/YARG.Core/Chart/Notes/Note.cs b/YARG.Core/Chart/Notes/Note.cs index 82d23982a..5fddde559 100644 --- a/YARG.Core/Chart/Notes/Note.cs +++ b/YARG.Core/Chart/Notes/Note.cs @@ -25,13 +25,13 @@ public abstract class Note : ChartEvent, ICloneable public NoteFlags Flags; - private TNote _originalPreviousNote; - private TNote _originalNextNote; + private TNote? _originalPreviousNote; + private TNote? _originalNextNote; - public TNote PreviousNote; - public TNote NextNote; + public TNote? PreviousNote; + public TNote? NextNote; - public TNote Parent { get; private set; } + public TNote? Parent { get; private set; } public IReadOnlyList ChildNotes => _childNotes; /// diff --git a/YARG.Core/Chart/SongChart.cs b/YARG.Core/Chart/SongChart.cs index f40fd9310..c897ef2d2 100644 --- a/YARG.Core/Chart/SongChart.cs +++ b/YARG.Core/Chart/SongChart.cs @@ -200,23 +200,20 @@ public void Append(SongChart song) public static SongChart FromFile(ParseSettings settings, string filePath) { - ISongLoader loader = new MoonSongLoader(); - loader.LoadSong(settings, filePath); - return new SongChart(loader); + var loader = MoonSongLoader.LoadSong(settings, filePath); + return new(loader); } public static SongChart FromMidi(ParseSettings settings, MidiFile midi) { - ISongLoader loader = new MoonSongLoader(); - loader.LoadMidi(settings, midi); - return new SongChart(loader); + var loader = MoonSongLoader.LoadMidi(settings, midi); + return new(loader); } public static SongChart FromDotChart(ParseSettings settings, string chartText) { - ISongLoader loader = new MoonSongLoader(); - loader.LoadDotChart(settings, chartText); - return new SongChart(loader); + var loader = MoonSongLoader.LoadDotChart(settings, chartText); + return new(loader); } public InstrumentTrack GetFiveFretTrack(Instrument instrument) diff --git a/YARG.Core/Chart/Sync/SyncTrack.cs b/YARG.Core/Chart/Sync/SyncTrack.cs index b07a825d3..ffdbc793d 100644 --- a/YARG.Core/Chart/Sync/SyncTrack.cs +++ b/YARG.Core/Chart/Sync/SyncTrack.cs @@ -191,6 +191,9 @@ public double TickToTime(uint tick) { // Find the current tempo marker at the given tick var currentTempo = Tempos.GetPrevious(tick); + if (currentTempo is null) + return 0; + return TickToTime(tick, currentTempo); // Fun little tidbit: if you're between two tempo markers, you can just lerp @@ -206,6 +209,9 @@ public uint TimeToTick(double time) // Find the current tempo marker at the given time var currentTempo = Tempos.GetPrevious(time); + if (currentTempo is null) + return 0; + return TimeToTick(time, currentTempo); } diff --git a/YARG.Core/Engine/BaseEngine.cs b/YARG.Core/Engine/BaseEngine.cs index b04e959ff..751e5cec7 100644 --- a/YARG.Core/Engine/BaseEngine.cs +++ b/YARG.Core/Engine/BaseEngine.cs @@ -27,15 +27,22 @@ public abstract class BaseEngine protected GameInput CurrentInput; - protected List Solos; + protected List Solos = new(); - protected BaseEngine(SyncTrack syncTrack) + protected BaseEngine(BaseEngineParameters parameters, SyncTrack syncTrack) { SyncTrack = syncTrack; Resolution = syncTrack.Resolution; TicksPerSustainPoint = Resolution / 25; + float[] multiplierThresholds = parameters.StarMultiplierThresholds; + StarScoreThresholds = new int[multiplierThresholds.Length]; + for (int i = 0; i < multiplierThresholds.Length; i++) + { + StarScoreThresholds[i] = (int)(BaseScore * multiplierThresholds[i]); + } + InputQueue = new Queue(); CurrentInput = new GameInput(-9999, -9999, -9999); } @@ -181,15 +188,15 @@ public abstract class BaseEngine chart, SyncTrack syncTrack, - TEngineParams engineParameters) : base(syncTrack) + TEngineParams engineParameters) : base(engineParameters, syncTrack) { Chart = chart; Notes = Chart.Notes; @@ -288,9 +295,9 @@ protected void UpdateStars() } } - protected virtual void StripStarPower(TNoteType note) + protected virtual void StripStarPower(TNoteType? note) { - if (!note.IsStarPower) + if (note is null || !note.IsStarPower) { return; } diff --git a/YARG.Core/Engine/BaseEngineParameters.cs b/YARG.Core/Engine/BaseEngineParameters.cs index 86485b34e..15692505a 100644 --- a/YARG.Core/Engine/BaseEngineParameters.cs +++ b/YARG.Core/Engine/BaseEngineParameters.cs @@ -24,6 +24,7 @@ public abstract class BaseEngineParameters : IBinarySerializable protected BaseEngineParameters() { + StarMultiplierThresholds = Array.Empty(); } protected BaseEngineParameters(double hitWindow, double frontBackRatio, float[] starMultiplierThresholds) diff --git a/YARG.Core/Engine/Drums/DrumsEngine.cs b/YARG.Core/Engine/Drums/DrumsEngine.cs index bdcdab725..dd321a833 100644 --- a/YARG.Core/Engine/Drums/DrumsEngine.cs +++ b/YARG.Core/Engine/Drums/DrumsEngine.cs @@ -10,22 +10,14 @@ public abstract class DrumsEngine : BaseEngine chart, SyncTrack syncTrack, DrumsEngineParameters engineParameters) : base(chart, syncTrack, engineParameters) { BaseScore = CalculateBaseScore(); - - float[] multiplierThresholds = engineParameters.StarMultiplierThresholds; - - StarScoreThresholds = new int[multiplierThresholds.Length]; - for (int i = 0; i < multiplierThresholds.Length; i++) - { - StarScoreThresholds[i] = (int)(BaseScore * multiplierThresholds[i]); - } } public override void Reset(bool keepCurrentButtons = false) diff --git a/YARG.Core/Engine/Guitar/GuitarEngine.cs b/YARG.Core/Engine/Guitar/GuitarEngine.cs index 51e6e397f..6943b424a 100644 --- a/YARG.Core/Engine/Guitar/GuitarEngine.cs +++ b/YARG.Core/Engine/Guitar/GuitarEngine.cs @@ -14,26 +14,17 @@ public abstract class GuitarEngine : BaseEngine ActiveSustains; + protected List ActiveSustains = new(); protected GuitarEngine(InstrumentDifficulty chart, SyncTrack syncTrack, GuitarEngineParameters engineParameters) : base(chart, syncTrack, engineParameters) { BaseScore = CalculateBaseScore(); - ActiveSustains = new List(); - - float[] multiplierThresholds = engineParameters.StarMultiplierThresholds; - - StarScoreThresholds = new int[multiplierThresholds.Length]; - for (int i = 0; i < multiplierThresholds.Length; i++) - { - StarScoreThresholds[i] = (int)(BaseScore * multiplierThresholds[i]); - } } public override void Reset(bool keepCurrentButtons = false) diff --git a/YARG.Core/Extensions/CollectionExtensions.cs b/YARG.Core/Extensions/CollectionExtensions.cs index 3e90f1ec7..b5fd6748c 100644 --- a/YARG.Core/Extensions/CollectionExtensions.cs +++ b/YARG.Core/Extensions/CollectionExtensions.cs @@ -55,7 +55,7 @@ public static T PickRandom(this IList list, Random random) /// The item from the list, or default if the list contains no elements.
/// If no exact match was found, the item returned is the one that matches the most closely. /// - public static TItem BinarySearch(this IList list, TSearch searchObject, + public static TItem? BinarySearch(this IList list, TSearch searchObject, Func comparer) { int index = list.BinarySearchIndex(searchObject, comparer); @@ -112,7 +112,7 @@ public static int BinarySearchIndex(this IList list, TSea /// /// The peeked value, if available; otherwise the default value of . /// - public static T PeekOrDefault(this Queue queue) + public static T? PeekOrDefault(this Queue queue) { if (queue.TryPeek(out var o)) { @@ -128,7 +128,7 @@ public static T PeekOrDefault(this Queue queue) /// /// The peeked value, if available; otherwise the default value of . /// - public static T DequeueOrDefault(this Queue queue) + public static T? DequeueOrDefault(this Queue queue) { if (queue.TryDequeue(out var o)) { diff --git a/YARG.Core/Extensions/ICloneable.cs b/YARG.Core/Extensions/ICloneable.cs index 31bc3ce8e..3cbb49052 100644 --- a/YARG.Core/Extensions/ICloneable.cs +++ b/YARG.Core/Extensions/ICloneable.cs @@ -1,3 +1,5 @@ +using System.Diagnostics.CodeAnalysis; + // Since this is a generic version of an existing interface // in the System namespace namespace System @@ -10,6 +12,7 @@ public interface ICloneable : ICloneable /// /// Creates a copy of this object with the same set of values. /// + [return: NotNull] // thanks Roslyn new T Clone(); object ICloneable.Clone() => Clone(); diff --git a/YARG.Core/Game/YargProfile.cs b/YARG.Core/Game/YargProfile.cs index efc1a7a33..2f2fc4bd1 100644 --- a/YARG.Core/Game/YargProfile.cs +++ b/YARG.Core/Game/YargProfile.cs @@ -94,7 +94,9 @@ public void ApplyModifiers(InstrumentDifficulty track) where TNote switch (Instrument.ToGameMode()) { case GameMode.FiveFretGuitar: - var guitarTrack = track as InstrumentDifficulty; + if (track is not InstrumentDifficulty guitarTrack) + throw new InvalidOperationException($"Cannot apply guitar modifiers to non-guitar track with notes of {typeof(TNote)}!"); + if(IsModifierActive(Modifier.AllStrums)) guitarTrack.ConvertToGuitarType(GuitarNoteType.Strum); else if(IsModifierActive(Modifier.AllHopos)) guitarTrack.ConvertToGuitarType(GuitarNoteType.Hopo); else if(IsModifierActive(Modifier.AllTaps)) guitarTrack.ConvertToGuitarType(GuitarNoteType.Tap); diff --git a/YARG.Core/MoonscraperChartParser/Events/ChartEvent.cs b/YARG.Core/MoonscraperChartParser/Events/ChartEvent.cs index 6e18928fb..2438f4f75 100644 --- a/YARG.Core/MoonscraperChartParser/Events/ChartEvent.cs +++ b/YARG.Core/MoonscraperChartParser/Events/ChartEvent.cs @@ -22,7 +22,7 @@ protected override bool Equals(SongObject b) { if (b.GetType() == typeof(ChartEvent)) { - var realB = b as ChartEvent; + var realB = (ChartEvent) b; return tick == realB.tick && eventName == realB.eventName; } else @@ -33,7 +33,7 @@ protected override bool LessThan(SongObject b) { if (b.GetType() == typeof(ChartEvent)) { - var realB = b as ChartEvent; + var realB = (ChartEvent) b; if (tick < b.tick) return true; else if (tick == b.tick) diff --git a/YARG.Core/MoonscraperChartParser/Events/ChartObject.cs b/YARG.Core/MoonscraperChartParser/Events/ChartObject.cs index 36190ff98..c31057bcc 100644 --- a/YARG.Core/MoonscraperChartParser/Events/ChartObject.cs +++ b/YARG.Core/MoonscraperChartParser/Events/ChartObject.cs @@ -11,7 +11,11 @@ internal abstract class ChartObject : SongObject [NonSerialized] public MoonChart chart; +// Non-nullable field 'chart' must contain a non-null value when exiting constructor +// 'chart' is assigned externally as part of this object being added to a chart +#pragma warning disable 8618 public ChartObject(uint position) : base(position) { } +#pragma warning restore 8618 // Clone needs to be hideable so it can return a different type in derived classes protected override SongObject SongClone() => ChartClone(); diff --git a/YARG.Core/MoonscraperChartParser/Events/Event.cs b/YARG.Core/MoonscraperChartParser/Events/Event.cs index 128ec8f80..a0b6e7d6a 100644 --- a/YARG.Core/MoonscraperChartParser/Events/Event.cs +++ b/YARG.Core/MoonscraperChartParser/Events/Event.cs @@ -22,7 +22,7 @@ protected override bool Equals(SongObject b) { if (base.Equals(b)) { - var realB = b as Event; + var realB = (Event) b; return realB != null && tick == realB.tick && title == realB.title; } @@ -33,7 +33,7 @@ protected override bool LessThan(SongObject b) { if (classID == b.classID) { - var realB = b as Event; + var realB = (Event) b; if (tick < b.tick) return true; else if (tick == b.tick) diff --git a/YARG.Core/MoonscraperChartParser/Events/MoonNote.cs b/YARG.Core/MoonscraperChartParser/Events/MoonNote.cs index 6a4ec5cde..b3eccabc8 100644 --- a/YARG.Core/MoonscraperChartParser/Events/MoonNote.cs +++ b/YARG.Core/MoonscraperChartParser/Events/MoonNote.cs @@ -144,11 +144,11 @@ public int vocalsPitch /// /// The previous note in the linked-list. /// - public MoonNote previous; + public MoonNote? previous; /// /// The next note in the linked-list. /// - public MoonNote next; + public MoonNote? next; public Chord chord => new(this); @@ -182,7 +182,7 @@ public bool forced /// /// Gets the next note in the linked-list that's not part of this note's chord. /// - public MoonNote NextSeperateMoonNote + public MoonNote? NextSeperateMoonNote { get { @@ -196,7 +196,7 @@ public MoonNote NextSeperateMoonNote /// /// Gets the previous note in the linked-list that's not part of this note's chord. /// - public MoonNote PreviousSeperateMoonNote + public MoonNote? PreviousSeperateMoonNote { get { @@ -211,7 +211,7 @@ protected override bool Equals(SongObject b) { if (b.GetType() == typeof(MoonNote)) { - var realB = b as MoonNote; + var realB = (MoonNote) b; if (tick == realB.tick && rawNote == realB.rawNote) return true; else @@ -225,7 +225,7 @@ protected override bool LessThan(SongObject b) { if (b.GetType() == typeof(MoonNote)) { - var realB = b as MoonNote; + var realB = (MoonNote) b; if (tick < b.tick) return true; else if (tick == b.tick) diff --git a/YARG.Core/MoonscraperChartParser/Events/SongObject.cs b/YARG.Core/MoonscraperChartParser/Events/SongObject.cs index 03714149f..8052e027b 100644 --- a/YARG.Core/MoonscraperChartParser/Events/SongObject.cs +++ b/YARG.Core/MoonscraperChartParser/Events/SongObject.cs @@ -20,10 +20,14 @@ internal abstract class SongObject public abstract int classID { get; } +// Non-nullable field 'song' must contain a non-null value when exiting constructor +// 'song' is assigned externally as part of this object being added to a song +#pragma warning disable 8618 public SongObject(uint _tick) { tick = _tick; } +#pragma warning restore 8618 /// /// Automatically converts the object's tick position into the time it will appear in the song. @@ -34,15 +38,15 @@ public SongObject(uint _tick) protected abstract SongObject SongClone(); public SongObject Clone() => SongClone(); - public static bool operator ==(SongObject a, SongObject b) + public static bool operator ==(SongObject? a, SongObject? b) { - bool aIsNull = a is null; - bool bIsNull = b is null; + if (ReferenceEquals(a, b)) + return true; - if (aIsNull || bIsNull) - return aIsNull == bIsNull; - else - return a.Equals(b); + if (a is null || b is null) + return false; + + return a.Equals(b); } protected virtual bool Equals(SongObject b) @@ -50,7 +54,7 @@ protected virtual bool Equals(SongObject b) return tick == b.tick && classID == b.classID; } - public static bool operator !=(SongObject a, SongObject b) + public static bool operator !=(SongObject? a, SongObject? b) { return !(a == b); } @@ -85,7 +89,7 @@ protected virtual bool LessThan(SongObject b) public override bool Equals(object obj) { - return base.Equals(obj); + return obj is SongObject songObj && this == songObj; } public override int GetHashCode() diff --git a/YARG.Core/MoonscraperChartParser/Events/SpecialPhrase.cs b/YARG.Core/MoonscraperChartParser/Events/SpecialPhrase.cs index d2e87eb7f..2f8ffb135 100644 --- a/YARG.Core/MoonscraperChartParser/Events/SpecialPhrase.cs +++ b/YARG.Core/MoonscraperChartParser/Events/SpecialPhrase.cs @@ -43,7 +43,7 @@ protected override bool Equals(SongObject b) { if (b.GetType() == typeof(SpecialPhrase)) { - var realB = b as SpecialPhrase; + var realB = (SpecialPhrase) b; if (tick == realB.tick && type == realB.type) return true; else @@ -57,7 +57,7 @@ protected override bool LessThan(SongObject b) { if (b.GetType() == typeof(SpecialPhrase)) { - var realB = b as SpecialPhrase; + var realB = (SpecialPhrase) b; if (tick < b.tick) return true; else if (tick == b.tick) @@ -80,7 +80,7 @@ public uint GetCappedLengthForPos(uint pos) else newLength = 0; - SpecialPhrase nextSp = null; + SpecialPhrase? nextSp = null; if (song != null && chart != null) { int arrayPos = SongObjectHelper.FindClosestPosition(this, chart.specialPhrases); diff --git a/YARG.Core/MoonscraperChartParser/IO/Midi/MidReader.ProcessLists.cs b/YARG.Core/MoonscraperChartParser/IO/Midi/MidReader.ProcessLists.cs index 1a8bd46c4..45d383afb 100644 --- a/YARG.Core/MoonscraperChartParser/IO/Midi/MidReader.ProcessLists.cs +++ b/YARG.Core/MoonscraperChartParser/IO/Midi/MidReader.ProcessLists.cs @@ -515,8 +515,11 @@ private static Dictionary BuildProGuitarNoteProcessDict() int key = (int)proString + difficultyStartRange; processFnDict.Add(key, (in EventProcessParams eventProcessParams) => { - var noteEvent = eventProcessParams.timedEvent.midiEvent as NoteEvent; - YargTrace.Assert(noteEvent != null, $"Wrong note event type passed to Pro Guitar note process. Expected: {typeof(NoteEvent)}, Actual: {eventProcessParams.timedEvent.midiEvent.GetType()}"); + if (eventProcessParams.timedEvent.midiEvent is not NoteEvent noteEvent) + { + YargTrace.Fail($"Wrong note event type passed to Pro Guitar note process. Expected: {typeof(NoteEvent)}, Actual: {eventProcessParams.timedEvent.midiEvent.GetType()}"); + return; + } if (noteEvent.Velocity < 100) { @@ -597,8 +600,11 @@ private static Dictionary BuildDrumsNoteProcessDict(bool en { processFnDict.Add(key, (in EventProcessParams eventProcessParams) => { - var noteEvent = eventProcessParams.timedEvent.midiEvent as NoteEvent; - YargTrace.Assert(noteEvent != null, $"Wrong note event type passed to drums note process. Expected: {typeof(NoteEvent)}, Actual: {eventProcessParams.timedEvent.midiEvent.GetType()}"); + if (eventProcessParams.timedEvent.midiEvent is not NoteEvent noteEvent) + { + YargTrace.Fail($"Wrong note event type passed to drums note process. Expected: {typeof(NoteEvent)}, Actual: {eventProcessParams.timedEvent.midiEvent.GetType()}"); + return; + } var flags = defaultFlags; switch (noteEvent.Velocity) diff --git a/YARG.Core/MoonscraperChartParser/IO/Midi/MidReader.cs b/YARG.Core/MoonscraperChartParser/IO/Midi/MidReader.cs index 337c81781..02ffc1701 100644 --- a/YARG.Core/MoonscraperChartParser/IO/Midi/MidReader.cs +++ b/YARG.Core/MoonscraperChartParser/IO/Midi/MidReader.cs @@ -10,6 +10,7 @@ using YARG.Core.Chart; using YARG.Core.Song; using YARG.Core.Extensions; +using System.Diagnostics.CodeAnalysis; namespace MoonscraperChartEditor.Song.IO { @@ -562,7 +563,7 @@ private static void ProcessSysExEvent(ref EventProcessParams processParams, SysE } private static bool TryFindMatchingNote(NoteEventQueue unpairedNotes, NoteEvent noteToMatch, - out NoteEvent matchingNote, out long matchTick, out int matchIndex) + [NotNullWhen(true)] out NoteEvent? matchingNote, out long matchTick, out int matchIndex) { for (int i = 0; i < unpairedNotes.Count; i++) { @@ -582,7 +583,7 @@ private static bool TryFindMatchingNote(NoteEventQueue unpairedNotes, NoteEvent } private static bool TryFindMatchingSysEx(SysExEventQueue unpairedSysex, PhaseShiftSysEx sysexToMatch, - out PhaseShiftSysEx matchingSysex, out long matchTick, out int matchIndex) + [NotNullWhen(true)] out PhaseShiftSysEx? matchingSysex, out long matchTick, out int matchIndex) { for (int i = 0; i < unpairedSysex.Count; i++) { @@ -773,8 +774,11 @@ private static void ProcessNoteOnEventAsFlagTogglePostDelay(in EventProcessParam private static void ProcessSysExEventPairAsForcedType(in EventProcessParams eventProcessParams, MoonNote.MoonNoteType noteType) { var timedEvent = eventProcessParams.timedEvent; - var startEvent = eventProcessParams.timedEvent.midiEvent as PhaseShiftSysEx; - YargTrace.Assert(startEvent != null, $"Wrong note event type passed to {nameof(ProcessSysExEventPairAsForcedType)}. Expected: {typeof(PhaseShiftSysEx)}, Actual: {eventProcessParams.timedEvent.midiEvent.GetType()}"); + if (eventProcessParams.timedEvent.midiEvent is not PhaseShiftSysEx startEvent) + { + YargTrace.Fail($"Wrong note event type passed to {nameof(ProcessSysExEventPairAsForcedType)}. Expected: {typeof(PhaseShiftSysEx)}, Actual: {eventProcessParams.timedEvent.midiEvent.GetType()}"); + return; + } uint startTick = (uint)timedEvent.startTick; uint endTick = (uint)timedEvent.endTick; @@ -805,8 +809,11 @@ private static void ProcessSysExEventPairAsForcedType(in EventProcessParams even private static void ProcessSysExEventPairAsOpenNoteModifier(in EventProcessParams eventProcessParams) { var timedEvent = eventProcessParams.timedEvent; - var startEvent = timedEvent.midiEvent as PhaseShiftSysEx; - YargTrace.Assert(startEvent != null, $"Wrong note event type passed to {nameof(ProcessSysExEventPairAsOpenNoteModifier)}. Expected: {typeof(PhaseShiftSysEx)}, Actual: {eventProcessParams.timedEvent.midiEvent.GetType()}"); + if (eventProcessParams.timedEvent.midiEvent is not PhaseShiftSysEx startEvent) + { + YargTrace.Fail($"Wrong note event type passed to {nameof(ProcessSysExEventPairAsOpenNoteModifier)}. Expected: {typeof(PhaseShiftSysEx)}, Actual: {eventProcessParams.timedEvent.midiEvent.GetType()}"); + return; + } uint startTick = (uint)timedEvent.startTick; uint endTick = (uint)timedEvent.endTick; diff --git a/YARG.Core/MoonscraperChartParser/IO/NoteFlagPriority.cs b/YARG.Core/MoonscraperChartParser/IO/NoteFlagPriority.cs index 056e991c5..1fc739349 100644 --- a/YARG.Core/MoonscraperChartParser/IO/NoteFlagPriority.cs +++ b/YARG.Core/MoonscraperChartParser/IO/NoteFlagPriority.cs @@ -2,6 +2,7 @@ // See LICENSE in project root for license information. using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; namespace MoonscraperChartEditor.Song.IO @@ -104,7 +105,7 @@ public bool AreFlagsValid(MoonNote.Flags flags) return true; } - public static bool AreFlagsValidForAll(MoonNote.Flags flags, out NoteFlagPriority invalidPriority) + public static bool AreFlagsValidForAll(MoonNote.Flags flags, [NotNullWhen(false)] out NoteFlagPriority? invalidPriority) { foreach (var priority in priorities) { diff --git a/YARG.Core/MoonscraperChartParser/Metadata.cs b/YARG.Core/MoonscraperChartParser/Metadata.cs index 38536ae8b..0dfe5e31e 100644 --- a/YARG.Core/MoonscraperChartParser/Metadata.cs +++ b/YARG.Core/MoonscraperChartParser/Metadata.cs @@ -1,17 +1,49 @@ // Copyright (c) 2016-2020 Alexander Ong // See LICENSE in project root for license information. +using System.Diagnostics.CodeAnalysis; + namespace MoonscraperChartEditor.Song { internal class Metadata { private string m_name, m_artist, m_charter, m_genre, m_album; - public string name { get => m_name; set => m_name = MakeValidMetadataString(value); } - public string artist { get => m_artist; set => m_artist = MakeValidMetadataString(value); } - public string charter { get => m_charter; set => m_charter = MakeValidMetadataString(value); } - public string genre { get => m_genre; set => m_genre = MakeValidMetadataString(value); } - public string album { get => m_album; set => m_album = MakeValidMetadataString(value); } + public string name + { + get => m_name; + [MemberNotNull(nameof(m_name))] + set => m_name = MakeValidMetadataString(value); + } + + public string artist + { + get => m_artist; + [MemberNotNull(nameof(m_artist))] + set => m_artist = MakeValidMetadataString(value); + } + + public string charter + { + get => m_charter; + [MemberNotNull(nameof(m_charter))] + set => m_charter = MakeValidMetadataString(value); + } + + public string genre + { + get => m_genre; + [MemberNotNull(nameof(m_genre))] + set => m_genre = MakeValidMetadataString(value); + } + + public string album + { + get => m_album; + [MemberNotNull(nameof(m_album))] + set => m_album = MakeValidMetadataString(value); + } + public string year; public int difficulty; diff --git a/YARG.Core/MoonscraperChartParser/MoonChart.cs b/YARG.Core/MoonscraperChartParser/MoonChart.cs index dfb112412..cf5cfcb73 100644 --- a/YARG.Core/MoonscraperChartParser/MoonChart.cs +++ b/YARG.Core/MoonscraperChartParser/MoonChart.cs @@ -103,12 +103,6 @@ public bool Remove(ChartObject chartObject, bool update = true) { bool success = SongObjectHelper.Remove(chartObject, _chartObjects); - if (success) - { - chartObject.chart = null; - chartObject.song = null; - } - if (update) UpdateCache(); diff --git a/YARG.Core/MoonscraperChartParser/MoonSong.cs b/YARG.Core/MoonscraperChartParser/MoonSong.cs index 91a871c47..7d33a6e95 100644 --- a/YARG.Core/MoonscraperChartParser/MoonSong.cs +++ b/YARG.Core/MoonscraperChartParser/MoonSong.cs @@ -144,7 +144,7 @@ public uint TimeToTick(double time, float resolution) /// /// The tick position /// Returns the value of the bpm that was found. - public BPM GetPrevBPM(uint position) + public BPM? GetPrevBPM(uint position) { return SongObjectHelper.GetPrevious(bpms, position); } @@ -154,12 +154,12 @@ public BPM GetPrevBPM(uint position) ///
/// The tick position /// Returns the value of the time signature that was found. - public TimeSignature GetPrevTS(uint position) + public TimeSignature? GetPrevTS(uint position) { return SongObjectHelper.GetPrevious(timeSignatures, position); } - public Section GetPrevSection(uint position) + public Section? GetPrevSection(uint position) { return SongObjectHelper.GetPrevious(sections, position); } @@ -223,11 +223,6 @@ public bool Remove(SyncTrack syncTrackObject, bool autoUpdate = true) success = SongObjectHelper.Remove(syncTrackObject, _syncTrack); } - if (success) - { - syncTrackObject.song = null; - } - if (autoUpdate) UpdateCache(); @@ -259,11 +254,6 @@ public bool Remove(Event eventObject, bool autoUpdate = true) { bool success = SongObjectHelper.Remove(eventObject, _events); - if (success) - { - eventObject.song = null; - } - if (autoUpdate) UpdateCache(); @@ -281,7 +271,7 @@ public static void UpdateCacheList(SongObjectCache cache, List objec { if (objectToCache.GetType() == typeof(T)) { - cacheObjectList.Add(objectToCache as T); + cacheObjectList.Add((T) objectToCache); } } } diff --git a/YARG.Core/MoonscraperChartParser/SongObjectHelper.cs b/YARG.Core/MoonscraperChartParser/SongObjectHelper.cs index df8bf6485..0011e8a3d 100644 --- a/YARG.Core/MoonscraperChartParser/SongObjectHelper.cs +++ b/YARG.Core/MoonscraperChartParser/SongObjectHelper.cs @@ -194,7 +194,7 @@ private static int FindPreviousPosition(System.Type type, int startPosition, } } - private static T FindPreviousOfType(System.Type type, int startPosition, IList list) where T : SongObject + private static T? FindPreviousOfType(System.Type type, int startPosition, IList list) where T : SongObject { int pos = FindPreviousPosition(type, startPosition, list); @@ -224,7 +224,7 @@ private static int FindNextPosition(System.Type type, int startPosition, ILis } } - private static T FindNextOfType(System.Type type, int startPosition, IList list) where T : SongObject + private static T? FindNextOfType(System.Type type, int startPosition, IList list) where T : SongObject { int pos = FindNextPosition(type, startPosition, list); if (pos == NOTFOUND) @@ -299,11 +299,9 @@ public static int Insert(T item, IList list) where T : SongObject insertionPos = list.Count - 1; } - if ((SongObject.ID)item.classID == SongObject.ID.Note) + if ((SongObject.ID)item.classID == SongObject.ID.Note && list[insertionPos] is MoonNote current) { // Update linked list - var current = list[insertionPos] as MoonNote; - var previous = FindPreviousOfType(typeof(MoonNote), insertionPos, list) as MoonNote; var next = FindNextOfType(typeof(MoonNote), insertionPos, list) as MoonNote; @@ -535,7 +533,7 @@ public static int GetIndexOfNext(IList songObjects, uint position) where T return closestPos; } - public static T GetPrevious(IList songObjects, uint position) where T : SongObject + public static T? GetPrevious(IList songObjects, uint position) where T : SongObject { int pos = GetIndexOfPrevious(songObjects, position); if (pos != NOTFOUND) @@ -544,7 +542,7 @@ public static T GetPrevious(IList songObjects, uint position) where T : So return null; } - public static T GetPreviousNonInclusive(IList songObjects, uint position) where T : SongObject + public static T? GetPreviousNonInclusive(IList songObjects, uint position) where T : SongObject { int pos = GetIndexOfPrevious(songObjects, position); if (pos != NOTFOUND) @@ -558,7 +556,7 @@ public static T GetPreviousNonInclusive(IList songObjects, uint position) return null; } - public static T GetNextNonInclusive(IList songObjects, uint position) where T : SongObject + public static T? GetNextNonInclusive(IList songObjects, uint position) where T : SongObject { int pos = GetIndexOfNext(songObjects, position); if (pos != NOTFOUND) diff --git a/YARG.Core/Replays/Replay.cs b/YARG.Core/Replays/Replay.cs index aebbc1c12..49c075cc7 100644 --- a/YARG.Core/Replays/Replay.cs +++ b/YARG.Core/Replays/Replay.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics.CodeAnalysis; using System.IO; using YARG.Core.Game; using YARG.Core.Song; @@ -49,6 +50,22 @@ public class Replay : IBinarySerializable public ReplayFrame[] Frames; + public Replay() + { + SongName = string.Empty; + ArtistName = string.Empty; + CharterName = string.Empty; + + ColorProfiles = Array.Empty(); + PlayerNames = Array.Empty(); + Frames = Array.Empty(); + } + + public Replay(BinaryReader reader, int version = 0) + { + Deserialize(reader, version); + } + public void Serialize(BinaryWriter writer) { writer.Write(SongName); @@ -78,6 +95,12 @@ public void Serialize(BinaryWriter writer) } } + [MemberNotNull(nameof(SongName))] + [MemberNotNull(nameof(ArtistName))] + [MemberNotNull(nameof(CharterName))] + [MemberNotNull(nameof(ColorProfiles))] + [MemberNotNull(nameof(PlayerNames))] + [MemberNotNull(nameof(Frames))] public void Deserialize(BinaryReader reader, int version = 0) { SongName = reader.ReadString(); diff --git a/YARG.Core/Replays/ReplayFrame.cs b/YARG.Core/Replays/ReplayFrame.cs index 3dc5fe738..ce15137b5 100644 --- a/YARG.Core/Replays/ReplayFrame.cs +++ b/YARG.Core/Replays/ReplayFrame.cs @@ -1,3 +1,5 @@ +using System; +using System.Diagnostics.CodeAnalysis; using System.IO; using YARG.Core.Engine; using YARG.Core.Engine.Drums; @@ -15,6 +17,18 @@ public class ReplayFrame : IBinarySerializable public int InputCount; public GameInput[] Inputs; + public ReplayFrame() + { + EngineParameters = new GuitarEngineParameters(); + Stats = new GuitarStats(); + Inputs = Array.Empty(); + } + + public ReplayFrame(BinaryReader reader, int version = 0) + { + Deserialize(reader, version); + } + public void Serialize(BinaryWriter writer) { PlayerInfo.Serialize(writer); @@ -30,10 +44,12 @@ public void Serialize(BinaryWriter writer) } } + [MemberNotNull(nameof(EngineParameters))] + [MemberNotNull(nameof(Stats))] + [MemberNotNull(nameof(Inputs))] public void Deserialize(BinaryReader reader, int version = 0) { - PlayerInfo = new ReplayPlayerInfo(); - PlayerInfo.Deserialize(reader, version); + PlayerInfo = new ReplayPlayerInfo(reader, version); switch (PlayerInfo.Profile.Instrument.ToGameMode()) { diff --git a/YARG.Core/Replays/ReplayIO.cs b/YARG.Core/Replays/ReplayIO.cs index 7b9a78fae..060df7d8c 100644 --- a/YARG.Core/Replays/ReplayIO.cs +++ b/YARG.Core/Replays/ReplayIO.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; @@ -20,7 +21,9 @@ public static class ReplayIO // Some versions may be invalidated (such as significant format changes) private static readonly int[] InvalidVersions = { 0, 1, 2 }; - public static ReplayReadResult ReadReplay(string path, out ReplayFile replayFile) + // note: [NotNullWhen(ReplayReadResult.Valid)] is not a valid form of [NotNullWhen], + // so replayFile will always be indicated as possibly being null + public static ReplayReadResult ReadReplay(string path, out ReplayFile? replayFile) { using var stream = File.OpenRead(path); using var reader = new BinaryReader(stream); diff --git a/YARG.Core/Replays/ReplayPlayerInfo.cs b/YARG.Core/Replays/ReplayPlayerInfo.cs index 0cb6e71fb..97904edcf 100644 --- a/YARG.Core/Replays/ReplayPlayerInfo.cs +++ b/YARG.Core/Replays/ReplayPlayerInfo.cs @@ -1,3 +1,4 @@ +using System.Diagnostics.CodeAnalysis; using System.IO; using YARG.Core.Game; using YARG.Core.Utility; @@ -10,6 +11,11 @@ public struct ReplayPlayerInfo : IBinarySerializable public int ColorProfileId; public YargProfile Profile; + public ReplayPlayerInfo(BinaryReader reader, int version = 0) : this() + { + Deserialize(reader, version); + } + public void Serialize(BinaryWriter writer) { writer.Write(PlayerId); @@ -18,6 +24,7 @@ public void Serialize(BinaryWriter writer) Profile.Serialize(writer); } + [MemberNotNull(nameof(Profile))] public void Deserialize(BinaryReader reader, int version = 0) { PlayerId = reader.ReadInt32(); diff --git a/YARG.Core/Song/Cache/CacheGroups/ConGroup.cs b/YARG.Core/Song/Cache/CacheGroups/ConGroup.cs index 2b4d03d3e..a35cb4a77 100644 --- a/YARG.Core/Song/Cache/CacheGroups/ConGroup.cs +++ b/YARG.Core/Song/Cache/CacheGroups/ConGroup.cs @@ -2,7 +2,6 @@ using System.IO; using YARG.Core.Song.Deserialization; -#nullable enable namespace YARG.Core.Song.Cache { public abstract class CONGroup diff --git a/YARG.Core/Song/Cache/CacheGroups/PackedCONGroup.cs b/YARG.Core/Song/Cache/CacheGroups/PackedCONGroup.cs index 0038b656f..a0e8a673c 100644 --- a/YARG.Core/Song/Cache/CacheGroups/PackedCONGroup.cs +++ b/YARG.Core/Song/Cache/CacheGroups/PackedCONGroup.cs @@ -3,7 +3,6 @@ using System.IO; using YARG.Core.Song.Deserialization; -#nullable enable namespace YARG.Core.Song.Cache { public class PackedCONGroup : CONGroup, ICacheGroup, IModificationGroup diff --git a/YARG.Core/Song/Cache/CacheGroups/UnpackedCONGroup.cs b/YARG.Core/Song/Cache/CacheGroups/UnpackedCONGroup.cs index e864ee903..0c6b4fe46 100644 --- a/YARG.Core/Song/Cache/CacheGroups/UnpackedCONGroup.cs +++ b/YARG.Core/Song/Cache/CacheGroups/UnpackedCONGroup.cs @@ -2,7 +2,6 @@ using System.IO; using YARG.Core.Song.Deserialization; -#nullable enable namespace YARG.Core.Song.Cache { public class UnpackedCONGroup : CONGroup, ICacheGroup diff --git a/YARG.Core/Song/Cache/CacheHandler.Parallel.cs b/YARG.Core/Song/Cache/CacheHandler.Parallel.cs index 542bb4c37..78e0e0a05 100644 --- a/YARG.Core/Song/Cache/CacheHandler.Parallel.cs +++ b/YARG.Core/Song/Cache/CacheHandler.Parallel.cs @@ -5,7 +5,6 @@ using System.Threading.Tasks; using YARG.Core.Song.Deserialization; -#nullable enable namespace YARG.Core.Song.Cache { public sealed partial class CacheHandler diff --git a/YARG.Core/Song/Cache/CacheHandler.Scanning.cs b/YARG.Core/Song/Cache/CacheHandler.Scanning.cs index 3cb75d077..5b4dbc76e 100644 --- a/YARG.Core/Song/Cache/CacheHandler.Scanning.cs +++ b/YARG.Core/Song/Cache/CacheHandler.Scanning.cs @@ -4,7 +4,6 @@ using System.Threading.Tasks; using YARG.Core.Song.Deserialization; -#nullable enable namespace YARG.Core.Song.Cache { public sealed partial class CacheHandler diff --git a/YARG.Core/Song/Cache/CacheHandler.Serialization.cs b/YARG.Core/Song/Cache/CacheHandler.Serialization.cs index c027a63ac..622641405 100644 --- a/YARG.Core/Song/Cache/CacheHandler.Serialization.cs +++ b/YARG.Core/Song/Cache/CacheHandler.Serialization.cs @@ -5,7 +5,6 @@ using YARG.Core.Extensions; using YARG.Core.Song.Deserialization; -#nullable enable namespace YARG.Core.Song.Cache { public sealed partial class CacheHandler diff --git a/YARG.Core/Song/Cache/CacheHandler.cs b/YARG.Core/Song/Cache/CacheHandler.cs index 240238aa0..6f6ff2be3 100644 --- a/YARG.Core/Song/Cache/CacheHandler.cs +++ b/YARG.Core/Song/Cache/CacheHandler.cs @@ -4,7 +4,6 @@ using System.Threading.Tasks; using YARG.Core.Song.Deserialization; -#nullable enable namespace YARG.Core.Song.Cache { public enum ScanProgress diff --git a/YARG.Core/Song/Deserialization/TXTReader/YARGTXTReader.cs b/YARG.Core/Song/Deserialization/TXTReader/YARGTXTReader.cs index a66abaf98..8e5e6c927 100644 --- a/YARG.Core/Song/Deserialization/TXTReader/YARGTXTReader.cs +++ b/YARG.Core/Song/Deserialization/TXTReader/YARGTXTReader.cs @@ -6,7 +6,6 @@ namespace YARG.Core.Song.Deserialization { -#nullable enable public class YARGTXTReader : YARGTXTReader_Base, ITXTReader { private static readonly byte[] BOM_UTF8 = { 0xEF, 0xBB, 0xBF }; diff --git a/YARG.Core/Song/Deserialization/YARGBinaryReader.cs b/YARG.Core/Song/Deserialization/YARGBinaryReader.cs index b6c8d2fdd..ca9da6cba 100644 --- a/YARG.Core/Song/Deserialization/YARGBinaryReader.cs +++ b/YARG.Core/Song/Deserialization/YARGBinaryReader.cs @@ -15,7 +15,6 @@ public enum Endianness BigEndian = 1, }; -#nullable enable public sealed class YARGBinaryReader { private readonly byte[] data; diff --git a/YARG.Core/Song/Deserialization/YARGCONLoader.cs b/YARG.Core/Song/Deserialization/YARGCONLoader.cs index 92c083e2d..886305ca6 100644 --- a/YARG.Core/Song/Deserialization/YARGCONLoader.cs +++ b/YARG.Core/Song/Deserialization/YARGCONLoader.cs @@ -86,7 +86,7 @@ public sealed class CONFile private const int BYTES_16BIT = 2; private const int BYTES_PER_BLOCK = 0x1000; -#nullable enable + public static CONFile? LoadCON(string filename) { byte[] buffer = new byte[BYTES_32BIT]; diff --git a/YARG.Core/Song/Deserialization/YARGMidiReader.cs b/YARG.Core/Song/Deserialization/YARGMidiReader.cs index f369b1fc0..7c5c04d8d 100644 --- a/YARG.Core/Song/Deserialization/YARGMidiReader.cs +++ b/YARG.Core/Song/Deserialization/YARGMidiReader.cs @@ -1,6 +1,7 @@ using System; using System.Buffers.Binary; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Text; using YARG.Core.Extensions; @@ -159,6 +160,7 @@ public YARGMidiReader(byte[] data) : this(new MemoryStream(data, 0, data.Length, public YARGMidiReader(string path) : this(new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)) { } + [MemberNotNullWhen(true, nameof(trackReader))] private bool LoadTrack(Span tag) { Span tagBuffer = stackalloc byte[4]; @@ -279,6 +281,7 @@ public void ExtractMidiNote(ref MidiNote note) note.velocity = trackReader.ReadByte(); } + [MemberNotNull(nameof(trackReader))] private void ProcessHeaderChunk() { if (!LoadTrack(TRACKTAGS[0])) diff --git a/YARG.Core/Song/Metadata/SongMetadata.Serialization.cs b/YARG.Core/Song/Metadata/SongMetadata.Serialization.cs index b312863d9..221d90e76 100644 --- a/YARG.Core/Song/Metadata/SongMetadata.Serialization.cs +++ b/YARG.Core/Song/Metadata/SongMetadata.Serialization.cs @@ -83,7 +83,6 @@ public void Serialize(BinaryWriter writer, CategoryCacheWriteNode node) _hash.Serialize(writer); } -#nullable enable private static AbridgedFileInfo? ParseFileInfo(YARGBinaryReader reader) { return ParseFileInfo(reader.ReadLEBString(), reader); diff --git a/YARG.Core/Song/Metadata/SongMetadata.SongIni.cs b/YARG.Core/Song/Metadata/SongMetadata.SongIni.cs index 124cdae94..225674aa9 100644 --- a/YARG.Core/Song/Metadata/SongMetadata.SongIni.cs +++ b/YARG.Core/Song/Metadata/SongMetadata.SongIni.cs @@ -21,7 +21,6 @@ public enum ChartType Chart, }; -#nullable enable [Serializable] public sealed class IniSubmetadata { diff --git a/YARG.Core/Song/Metadata/SongMetadata.SongPackedRBCON.cs b/YARG.Core/Song/Metadata/SongMetadata.SongPackedRBCON.cs index d588e3276..499be29dd 100644 --- a/YARG.Core/Song/Metadata/SongMetadata.SongPackedRBCON.cs +++ b/YARG.Core/Song/Metadata/SongMetadata.SongPackedRBCON.cs @@ -6,7 +6,6 @@ using YARG.Core.Song.Cache; using YARG.Core.Song.Deserialization; -#nullable enable namespace YARG.Core.Song { public sealed partial class SongMetadata diff --git a/YARG.Core/Song/Metadata/SongMetadata.SongRBCON.cs b/YARG.Core/Song/Metadata/SongMetadata.SongRBCON.cs index ee390f32b..1eadb3814 100644 --- a/YARG.Core/Song/Metadata/SongMetadata.SongRBCON.cs +++ b/YARG.Core/Song/Metadata/SongMetadata.SongRBCON.cs @@ -10,7 +10,6 @@ using YARG.Core.Song.Deserialization; using YARG.Core.Song.Preparsers; -#nullable enable namespace YARG.Core.Song { public sealed partial class SongMetadata diff --git a/YARG.Core/Song/Metadata/SongMetadata.SongUnpackedRBCON.cs b/YARG.Core/Song/Metadata/SongMetadata.SongUnpackedRBCON.cs index 3457e026a..4f4268d6a 100644 --- a/YARG.Core/Song/Metadata/SongMetadata.SongUnpackedRBCON.cs +++ b/YARG.Core/Song/Metadata/SongMetadata.SongUnpackedRBCON.cs @@ -6,7 +6,6 @@ using YARG.Core.Song.Cache; using YARG.Core.Song.Deserialization; -#nullable enable namespace YARG.Core.Song { public sealed partial class SongMetadata diff --git a/YARG.Core/Song/Metadata/SongMetadata.cs b/YARG.Core/Song/Metadata/SongMetadata.cs index bac4df368..bf8614f99 100644 --- a/YARG.Core/Song/Metadata/SongMetadata.cs +++ b/YARG.Core/Song/Metadata/SongMetadata.cs @@ -2,7 +2,6 @@ using System.Text.RegularExpressions; using YARG.Core.Chart; -#nullable enable namespace YARG.Core.Song { public enum ScanResult diff --git a/YARG.Core/Song/Metadata/Types/RBProUpgrade.cs b/YARG.Core/Song/Metadata/Types/RBProUpgrade.cs index 8857f6442..9b1768d6e 100644 --- a/YARG.Core/Song/Metadata/Types/RBProUpgrade.cs +++ b/YARG.Core/Song/Metadata/Types/RBProUpgrade.cs @@ -4,7 +4,6 @@ using System.Text; using YARG.Core.Song.Deserialization; -#nullable enable namespace YARG.Core.Song { public interface IRBProUpgrade diff --git a/YARG.Core/YARG.Core.csproj b/YARG.Core/YARG.Core.csproj index a42b32ddc..fa3daf140 100644 --- a/YARG.Core/YARG.Core.csproj +++ b/YARG.Core/YARG.Core.csproj @@ -5,11 +5,16 @@ 9 true True + enable + + runtime; build; native; contentfiles; analyzers; buildtransitive + all +