Skip to content

Commit

Permalink
Enable nullable analysis and fix all nullable warnings (YARC-Official#75
Browse files Browse the repository at this point in the history
)

* Enable nullable analysis globally for YARG.Core

* Add PolySharp for attribute polyfills

* Fix nullable warnings in Moonscraper

* Fix nullable warnings in YARG.Core.Extensions

* Fix nullable warnings in YARG.Core.Game

* Fix nullable warnings in YARG.Core.Chart

* Fix nullable warnings in YARG.Core.Engine

* Fix nullable warnings in YARG.Core.Replays

* Fix nullable warnings in YARG.Core.Song
  • Loading branch information
TheNathannator authored Sep 18, 2023
1 parent 78c5915 commit ecb20ef
Show file tree
Hide file tree
Showing 51 changed files with 242 additions and 171 deletions.
12 changes: 6 additions & 6 deletions YARG.Core/Chart/Events/ChartEventExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public static uint GetLastTick<TEvent>(this IList<TEvent> events)
return chartEvent.TickEnd;
}

public static TEvent GetPrevious<TEvent>(this IList<TEvent> events, double time)
public static TEvent? GetPrevious<TEvent>(this IList<TEvent> events, double time)
where TEvent : ChartEvent
{
int index = GetIndexOfPrevious(events, time);
Expand All @@ -94,7 +94,7 @@ public static TEvent GetPrevious<TEvent>(this IList<TEvent> events, double time)
return events[index];
}

public static TEvent GetPrevious<TEvent>(this IList<TEvent> events, uint tick)
public static TEvent? GetPrevious<TEvent>(this IList<TEvent> events, uint tick)
where TEvent : ChartEvent
{
int index = GetIndexOfPrevious(events, tick);
Expand All @@ -104,7 +104,7 @@ public static TEvent GetPrevious<TEvent>(this IList<TEvent> events, uint tick)
return events[index];
}

public static TEvent GetNext<TEvent>(this IList<TEvent> events, double time)
public static TEvent? GetNext<TEvent>(this IList<TEvent> events, double time)
where TEvent : ChartEvent
{
int index = GetIndexOfNext(events, time);
Expand All @@ -114,7 +114,7 @@ public static TEvent GetNext<TEvent>(this IList<TEvent> events, double time)
return events[index];
}

public static TEvent GetNext<TEvent>(this IList<TEvent> events, uint tick)
public static TEvent? GetNext<TEvent>(this IList<TEvent> events, uint tick)
where TEvent : ChartEvent
{
int index = GetIndexOfNext(events, tick);
Expand Down Expand Up @@ -234,7 +234,7 @@ public static bool GetEventRange<TEvent>(this IList<TEvent> events, uint startTi
return true;
}

public static TEvent FindClosestEvent<TEvent>(this IList<TEvent> events, double time)
public static TEvent? FindClosestEvent<TEvent>(this IList<TEvent> events, double time)
where TEvent : ChartEvent
{
return events.BinarySearch(time, Compare);
Expand All @@ -250,7 +250,7 @@ static int Compare(TEvent currentEvent, double targetTime)
}
}

public static TEvent FindClosestEvent<TEvent>(this IList<TEvent> events, uint tick)
public static TEvent? FindClosestEvent<TEvent>(this IList<TEvent> events, uint tick)
where TEvent : ChartEvent
{
return events.BinarySearch(tick, Compare);
Expand Down
5 changes: 0 additions & 5 deletions YARG.Core/Chart/Loaders/ISongLoader.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Collections.Generic;
using Melanchall.DryWetMidi.Core;

namespace YARG.Core.Chart
{
Expand All @@ -8,10 +7,6 @@ namespace YARG.Core.Chart
/// </summary>
internal interface ISongLoader
{
void LoadSong(ParseSettings settings, string filePath);
void LoadMidi(ParseSettings settings, MidiFile midi);
void LoadDotChart(ParseSettings settings, string chartText);

List<TextEvent> LoadGlobalEvents();
SyncTrack LoadSyncTrack();
VenueTrack LoadVenueTrack();
Expand Down
6 changes: 3 additions & 3 deletions YARG.Core/Chart/Loaders/MoonSong/MoonSongLoader.Venue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,8 @@ public VenueTrack LoadVenueTrack()
var otherEvents = new List<VenueTextEvent>(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;

Expand Down Expand Up @@ -192,7 +192,7 @@ public VenueTrack LoadVenueTrack()
}

private void HandlePerformerEvent(List<PerformerEvent> events, PerformerEventType type, MoonVenueEvent moonEvent,
ref MoonVenueEvent currentEvent, ref Performer performers)
ref MoonVenueEvent? currentEvent, ref Performer performers)
{
// First event
if (currentEvent == null)
Expand Down
2 changes: 1 addition & 1 deletion YARG.Core/Chart/Loaders/MoonSong/MoonSongLoader.Vocals.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ private List<VocalsPhrase> GetVocalsPhrases(MoonChart moonChart, int harmonyPart
// Go through each note and lyric in the phrase
var notes = new List<VocalNote>();
var lyrics = new List<TextEvent>();
VocalNote previousNote = null;
VocalNote? previousNote = null;
while (moonNoteIndex < moonChart.notes.Count)
{
var moonNote = moonChart.notes[moonNoteIndex];
Expand Down
34 changes: 17 additions & 17 deletions YARG.Core/Chart/Loaders/MoonSong/MoonSongLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,16 @@ private delegate TNote CreateNoteDelegate<TNote>(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
{
Expand All @@ -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<TextEvent> LoadGlobalEvents()
Expand Down Expand Up @@ -125,7 +125,7 @@ public SyncTrack LoadSyncTrack()
}

private InstrumentDifficulty<TNote> LoadDifficulty<TNote>(Instrument instrument, Difficulty difficulty,
CreateNoteDelegate<TNote> createNote, ProcessTextDelegate processText = null)
CreateNoteDelegate<TNote> createNote, ProcessTextDelegate? processText = null)
where TNote : Note<TNote>
{
_currentInstrument = instrument;
Expand All @@ -139,7 +139,7 @@ private InstrumentDifficulty<TNote> LoadDifficulty<TNote>(Instrument instrument,
}

private List<TNote> GetNotes<TNote>(MoonChart moonChart, Difficulty difficulty,
CreateNoteDelegate<TNote> createNote, ProcessTextDelegate processText = null)
CreateNoteDelegate<TNote> createNote, ProcessTextDelegate? processText = null)
where TNote : Note<TNote>
{
var notes = new List<TNote>(moonChart.notes.Count);
Expand Down
10 changes: 5 additions & 5 deletions YARG.Core/Chart/Notes/Note.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ public abstract class Note<TNote> : ChartEvent, ICloneable<TNote>

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<TNote> ChildNotes => _childNotes;

/// <summary>
Expand Down
15 changes: 6 additions & 9 deletions YARG.Core/Chart/SongChart.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<GuitarNote> GetFiveFretTrack(Instrument instrument)
Expand Down
6 changes: 6 additions & 0 deletions YARG.Core/Chart/Sync/SyncTrack.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);
}

Expand Down
31 changes: 19 additions & 12 deletions YARG.Core/Engine/BaseEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,22 @@ public abstract class BaseEngine

protected GameInput CurrentInput;

protected List<SoloSection> Solos;
protected List<SoloSection> 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<GameInput>();
CurrentInput = new GameInput(-9999, -9999, -9999);
}
Expand Down Expand Up @@ -181,15 +188,15 @@ public abstract class BaseEngine<TNoteType, TActionType, TEngineParams, TEngineS

public delegate void SoloEndEvent(SoloSection soloSection);

public NoteHitEvent OnNoteHit;
public NoteMissedEvent OnNoteMissed;
public NoteHitEvent? OnNoteHit;
public NoteMissedEvent? OnNoteMissed;

public StarPowerPhraseHitEvent OnStarPowerPhraseHit;
public StarPowerPhraseMissEvent OnStarPowerPhraseMissed;
public StarPowerStatusEvent OnStarPowerStatus;
public StarPowerPhraseHitEvent? OnStarPowerPhraseHit;
public StarPowerPhraseMissEvent? OnStarPowerPhraseMissed;
public StarPowerStatusEvent? OnStarPowerStatus;

public SoloStartEvent OnSoloStart;
public SoloEndEvent OnSoloEnd;
public SoloStartEvent? OnSoloStart;
public SoloEndEvent? OnSoloEnd;

public readonly TEngineStats EngineStats;

Expand All @@ -201,7 +208,7 @@ public abstract class BaseEngine<TNoteType, TActionType, TEngineParams, TEngineS
public TEngineState State;

protected BaseEngine(InstrumentDifficulty<TNoteType> chart, SyncTrack syncTrack,
TEngineParams engineParameters) : base(syncTrack)
TEngineParams engineParameters) : base(engineParameters, syncTrack)
{
Chart = chart;
Notes = Chart.Notes;
Expand Down Expand Up @@ -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;
}
Expand Down
1 change: 1 addition & 0 deletions YARG.Core/Engine/BaseEngineParameters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public abstract class BaseEngineParameters : IBinarySerializable

protected BaseEngineParameters()
{
StarMultiplierThresholds = Array.Empty<float>();
}

protected BaseEngineParameters(double hitWindow, double frontBackRatio, float[] starMultiplierThresholds)
Expand Down
12 changes: 2 additions & 10 deletions YARG.Core/Engine/Drums/DrumsEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,14 @@ public abstract class DrumsEngine : BaseEngine<DrumNote, DrumsAction, DrumsEngin

public delegate void PadHitEvent(DrumsAction action, bool noteWasHit);

public OverhitEvent OnOverhit;
public PadHitEvent OnPadHit;
public OverhitEvent? OnOverhit;
public PadHitEvent? OnPadHit;

protected DrumsEngine(InstrumentDifficulty<DrumNote> 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)
Expand Down
17 changes: 4 additions & 13 deletions YARG.Core/Engine/Guitar/GuitarEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,17 @@ public abstract class GuitarEngine : BaseEngine<GuitarNote, GuitarAction, Guitar

public delegate void SustainEndEvent(GuitarNote note, double timeEnded);

public OverstrumEvent OnOverstrum;
public SustainStartEvent OnSustainStart;
public SustainEndEvent OnSustainEnd;
public OverstrumEvent? OnOverstrum;
public SustainStartEvent? OnSustainStart;
public SustainEndEvent? OnSustainEnd;

protected List<GuitarNote> ActiveSustains;
protected List<GuitarNote> ActiveSustains = new();

protected GuitarEngine(InstrumentDifficulty<GuitarNote> chart, SyncTrack syncTrack,
GuitarEngineParameters engineParameters)
: base(chart, syncTrack, engineParameters)
{
BaseScore = CalculateBaseScore();
ActiveSustains = new List<GuitarNote>();

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)
Expand Down
6 changes: 3 additions & 3 deletions YARG.Core/Extensions/CollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public static T PickRandom<T>(this IList<T> list, Random random)
/// The item from the list, or default if the list contains no elements.<br/>
/// If no exact match was found, the item returned is the one that matches the most closely.
/// </returns>
public static TItem BinarySearch<TItem, TSearch>(this IList<TItem> list, TSearch searchObject,
public static TItem? BinarySearch<TItem, TSearch>(this IList<TItem> list, TSearch searchObject,
Func<TItem, TSearch, int> comparer)
{
int index = list.BinarySearchIndex(searchObject, comparer);
Expand Down Expand Up @@ -112,7 +112,7 @@ public static int BinarySearchIndex<TItem, TSearch>(this IList<TItem> list, TSea
/// <returns>
/// The peeked value, if available; otherwise the default value of <typeparamref name="T"/>.
/// </returns>
public static T PeekOrDefault<T>(this Queue<T> queue)
public static T? PeekOrDefault<T>(this Queue<T> queue)
{
if (queue.TryPeek(out var o))
{
Expand All @@ -128,7 +128,7 @@ public static T PeekOrDefault<T>(this Queue<T> queue)
/// <returns>
/// The peeked value, if available; otherwise the default value of <typeparamref name="T"/>.
/// </returns>
public static T DequeueOrDefault<T>(this Queue<T> queue)
public static T? DequeueOrDefault<T>(this Queue<T> queue)
{
if (queue.TryDequeue(out var o))
{
Expand Down
Loading

0 comments on commit ecb20ef

Please sign in to comment.