This change pulls back a significant degree of overspecialisation and
rigidity in the class structure of `HitWindows` to make subsequent
changes to hit windows, whose purpose is to improve replay playback
accuracy, possible to do cleanly.
Notably:
- `HitWindows` is full abstract now. In a few use cases, and as a
reference for ruleset implementors, `DefaultHitWindows` is provided as
a separate class instead.
This fixes the weirdness wherein `HitWindows` always declared 6 fields
for result types but some of them would never be set to a non-zero
value or read.
- `HitWindow.GetRanges()` is deleted because it is overspecialised and
prevents being able to adjust hitwindows by ±0.5ms cleanly which will
be required later.
The fallout of this is that the assertion that used `GetRanges()` in
the `HitWindows` ctor must use something else now, and the closest
thing to it was `GetAllAvailableWindows()`, which didn't return
the miss window - so I made it return the miss window and fixed the
one consumer that didn't want it (bar hit error meter) to skip it.
- Diff also contains some clean-up around `DifficultyRange` to unify
handling of it.
As pointed out in review, if the current time is after the end of the
slider, the correct hit object to use for sample retrieval is the object
itself, not any nested object.