1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-13 07:22:54 +08:00

Merge branch 'master' into ui-scaling-keybind

This commit is contained in:
Dean Herbert 2021-10-28 13:03:21 +09:00
commit ad1bd4e48e
296 changed files with 1617 additions and 897 deletions

View File

@ -113,7 +113,7 @@ dotnet_style_qualification_for_event = false:warning
dotnet_style_predefined_type_for_locals_parameters_members = true:warning dotnet_style_predefined_type_for_locals_parameters_members = true:warning
dotnet_style_predefined_type_for_member_access = true:warning dotnet_style_predefined_type_for_member_access = true:warning
csharp_style_var_when_type_is_apparent = true:none csharp_style_var_when_type_is_apparent = true:none
csharp_style_var_for_built_in_types = true:none csharp_style_var_for_built_in_types = false:warning
csharp_style_var_elsewhere = true:silent csharp_style_var_elsewhere = true:silent
#Style - modifiers #Style - modifiers

View File

@ -156,7 +156,7 @@ namespace osu.Desktop
{ {
lock (importableFiles) lock (importableFiles)
{ {
var firstExtension = Path.GetExtension(filePaths.First()); string firstExtension = Path.GetExtension(filePaths.First());
if (filePaths.Any(f => Path.GetExtension(f) != firstExtension)) return; if (filePaths.Any(f => Path.GetExtension(f) != firstExtension)) return;
@ -177,7 +177,7 @@ namespace osu.Desktop
{ {
Logger.Log($"Handling batch import of {importableFiles.Count} files"); Logger.Log($"Handling batch import of {importableFiles.Count} files");
var paths = importableFiles.ToArray(); string[] paths = importableFiles.ToArray();
importableFiles.Clear(); importableFiles.Clear();
Task.Factory.StartNew(() => Import(paths), TaskCreationOptions.LongRunning); Task.Factory.StartNew(() => Import(paths), TaskCreationOptions.LongRunning);

View File

@ -22,17 +22,17 @@ namespace osu.Desktop
public static int Main(string[] args) public static int Main(string[] args)
{ {
// Back up the cwd before DesktopGameHost changes it // Back up the cwd before DesktopGameHost changes it
var cwd = Environment.CurrentDirectory; string cwd = Environment.CurrentDirectory;
string gameName = base_game_name; string gameName = base_game_name;
bool tournamentClient = false; bool tournamentClient = false;
foreach (var arg in args) foreach (string arg in args)
{ {
var split = arg.Split('='); string[] split = arg.Split('=');
var key = split[0]; string key = split[0];
var val = split.Length > 1 ? split[1] : string.Empty; string val = split.Length > 1 ? split[1] : string.Empty;
switch (key) switch (key)
{ {
@ -62,7 +62,7 @@ namespace osu.Desktop
{ {
var importer = new ArchiveImportIPCChannel(host); var importer = new ArchiveImportIPCChannel(host);
foreach (var file in args) foreach (string file in args)
{ {
Console.WriteLine(@"Importing {0}", file); Console.WriteLine(@"Importing {0}", file);
if (!importer.ImportAsync(Path.GetFullPath(file, cwd)).Wait(3000)) if (!importer.ImportAsync(Path.GetFullPath(file, cwd)).Wait(3000))

View File

@ -49,7 +49,7 @@ namespace osu.Game.Rulesets.Catch.Tests.Editor
AddAssert("correct outline count", () => AddAssert("correct outline count", () =>
{ {
var expected = hitObject.NestedHitObjects.Count(h => !(h is TinyDroplet)); int expected = hitObject.NestedHitObjects.Count(h => !(h is TinyDroplet));
return this.ChildrenOfType<FruitOutline>().Count() == expected; return this.ChildrenOfType<FruitOutline>().Count() == expected;
}); });
AddAssert("correct vertex piece count", () => AddAssert("correct vertex piece count", () =>

View File

@ -103,7 +103,7 @@ namespace osu.Game.Rulesets.Catch.Tests
[Test] [Test]
public void TestCatcherCatchWidth() public void TestCatcherCatchWidth()
{ {
var halfWidth = Catcher.CalculateCatchWidth(new BeatmapDifficulty { CircleSize = 0 }) / 2; float halfWidth = Catcher.CalculateCatchWidth(new BeatmapDifficulty { CircleSize = 0 }) / 2;
AddStep("catch fruit", () => AddStep("catch fruit", () =>
{ {
attemptCatch(new Fruit { X = -halfWidth + 1 }); attemptCatch(new Fruit { X = -halfWidth + 1 });
@ -237,7 +237,7 @@ namespace osu.Game.Rulesets.Catch.Tests
private void attemptCatch(Func<CatchHitObject> hitObject, int count) private void attemptCatch(Func<CatchHitObject> hitObject, int count)
{ {
for (var i = 0; i < count; i++) for (int i = 0; i < count; i++)
attemptCatch(hitObject(), out _, out _); attemptCatch(hitObject(), out _, out _);
} }

View File

@ -118,7 +118,7 @@ namespace osu.Game.Rulesets.Catch.Tests
private void spawnJuiceStream(bool hit = false) private void spawnJuiceStream(bool hit = false)
{ {
var xCoords = getXCoords(hit); float xCoords = getXCoords(hit);
var juice = new JuiceStream var juice = new JuiceStream
{ {

View File

@ -233,7 +233,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps
int thisDirection = nextObject.EffectiveX > currentObject.EffectiveX ? 1 : -1; int thisDirection = nextObject.EffectiveX > currentObject.EffectiveX ? 1 : -1;
double timeToNext = nextObject.StartTime - currentObject.StartTime - 1000f / 60f / 4; // 1/4th of a frame of grace time, taken from osu-stable double timeToNext = nextObject.StartTime - currentObject.StartTime - 1000f / 60f / 4; // 1/4th of a frame of grace time, taken from osu-stable
double distanceToNext = Math.Abs(nextObject.EffectiveX - currentObject.EffectiveX) - (lastDirection == thisDirection ? lastExcess : halfCatcherWidth); double distanceToNext = Math.Abs(nextObject.EffectiveX - currentObject.EffectiveX) - (lastDirection == thisDirection ? lastExcess : halfCatcherWidth);
float distanceToHyper = (float)(timeToNext * Catcher.BASE_SPEED - distanceToNext); float distanceToHyper = (float)(timeToNext * Catcher.BASE_DASH_SPEED - distanceToNext);
if (distanceToHyper < 0) if (distanceToHyper < 0)
{ {

View File

@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty.Preprocessing
: base(hitObject, lastObject, clockRate) : base(hitObject, lastObject, clockRate)
{ {
// We will scale everything by this factor, so we can assume a uniform CircleSize among beatmaps. // We will scale everything by this factor, so we can assume a uniform CircleSize among beatmaps.
var scalingFactor = normalized_hitobject_radius / halfCatcherWidth; float scalingFactor = normalized_hitobject_radius / halfCatcherWidth;
NormalizedPosition = BaseObject.EffectiveX * scalingFactor; NormalizedPosition = BaseObject.EffectiveX * scalingFactor;
LastNormalizedPosition = LastObject.EffectiveX * scalingFactor; LastNormalizedPosition = LastObject.EffectiveX * scalingFactor;

View File

@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Catch.Edit
public float StartX { get; set; } public float StartX { get; set; }
private const double max_vertical_line_length_in_time = CatchPlayfield.WIDTH / Catcher.BASE_SPEED * 2; private const double max_vertical_line_length_in_time = CatchPlayfield.WIDTH / Catcher.BASE_WALK_SPEED;
private readonly double[] velocities; private readonly double[] velocities;

View File

@ -51,8 +51,8 @@ namespace osu.Game.Rulesets.Catch.Edit
LayerBelowRuleset.Add(distanceSnapGrid = new CatchDistanceSnapGrid(new[] LayerBelowRuleset.Add(distanceSnapGrid = new CatchDistanceSnapGrid(new[]
{ {
0.0, 0.0,
Catcher.BASE_SPEED, -Catcher.BASE_SPEED, Catcher.BASE_DASH_SPEED, -Catcher.BASE_DASH_SPEED,
Catcher.BASE_SPEED / 2, -Catcher.BASE_SPEED / 2, Catcher.BASE_WALK_SPEED, -Catcher.BASE_WALK_SPEED,
})); }));
} }

View File

@ -52,8 +52,8 @@ namespace osu.Game.Rulesets.Catch.Mods
{ {
var hitObject = drawable.HitObject; var hitObject = drawable.HitObject;
var offset = hitObject.TimePreempt * fade_out_offset_multiplier; double offset = hitObject.TimePreempt * fade_out_offset_multiplier;
var duration = offset - hitObject.TimePreempt * fade_out_duration_multiplier; double duration = offset - hitObject.TimePreempt * fade_out_duration_multiplier;
using (drawable.BeginAbsoluteSequence(hitObject.StartTime - offset)) using (drawable.BeginAbsoluteSequence(hitObject.StartTime - offset))
drawable.FadeOut(duration); drawable.FadeOut(duration);

View File

@ -26,9 +26,6 @@ namespace osu.Game.Rulesets.Catch.Replays
if (Beatmap.HitObjects.Count == 0) if (Beatmap.HitObjects.Count == 0)
return; return;
// todo: add support for HT DT
const double dash_speed = Catcher.BASE_SPEED;
const double movement_speed = dash_speed / 2;
float lastPosition = CatchPlayfield.CENTER_X; float lastPosition = CatchPlayfield.CENTER_X;
double lastTime = 0; double lastTime = 0;
@ -47,8 +44,8 @@ namespace osu.Game.Rulesets.Catch.Replays
// The case where positionChange > 0 and timeAvailable == 0 results in PositiveInfinity which provides expected beheaviour. // The case where positionChange > 0 and timeAvailable == 0 results in PositiveInfinity which provides expected beheaviour.
double speedRequired = positionChange == 0 ? 0 : positionChange / timeAvailable; double speedRequired = positionChange == 0 ? 0 : positionChange / timeAvailable;
bool dashRequired = speedRequired > movement_speed; bool dashRequired = speedRequired > Catcher.BASE_WALK_SPEED;
bool impossibleJump = speedRequired > movement_speed * 2; bool impossibleJump = speedRequired > Catcher.BASE_DASH_SPEED;
// todo: get correct catcher size, based on difficulty CS. // todo: get correct catcher size, based on difficulty CS.
const float catcher_width_half = Catcher.BASE_SIZE * 0.3f * 0.5f; const float catcher_width_half = Catcher.BASE_SIZE * 0.3f * 0.5f;
@ -73,7 +70,7 @@ namespace osu.Game.Rulesets.Catch.Replays
else if (dashRequired) else if (dashRequired)
{ {
// we do a movement in two parts - the dash part then the normal part... // we do a movement in two parts - the dash part then the normal part...
double timeAtNormalSpeed = positionChange / movement_speed; double timeAtNormalSpeed = positionChange / Catcher.BASE_WALK_SPEED;
double timeWeNeedToSave = timeAtNormalSpeed - timeAvailable; double timeWeNeedToSave = timeAtNormalSpeed - timeAvailable;
double timeAtDashSpeed = timeWeNeedToSave / 2; double timeAtDashSpeed = timeWeNeedToSave / 2;
@ -86,7 +83,7 @@ namespace osu.Game.Rulesets.Catch.Replays
} }
else else
{ {
double timeBefore = positionChange / movement_speed; double timeBefore = positionChange / Catcher.BASE_WALK_SPEED;
addFrame(h.StartTime - timeBefore, lastPosition); addFrame(h.StartTime - timeBefore, lastPosition);
addFrame(h.StartTime, h.EffectiveX); addFrame(h.StartTime, h.EffectiveX);

View File

@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Catch.Replays
public override void CollectPendingInputs(List<IInput> inputs) public override void CollectPendingInputs(List<IInput> inputs)
{ {
var position = Interpolation.ValueAt(CurrentTime, StartFrame.Position, EndFrame.Position, StartFrame.Time, EndFrame.Time); float position = Interpolation.ValueAt(CurrentTime, StartFrame.Position, EndFrame.Position, StartFrame.Time, EndFrame.Time);
inputs.Add(new CatchReplayState inputs.Add(new CatchReplayState
{ {

View File

@ -66,7 +66,7 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy
return null; return null;
case CatchSkinComponents.Catcher: case CatchSkinComponents.Catcher:
var version = GetConfig<LegacySkinConfiguration.LegacySetting, decimal>(LegacySkinConfiguration.LegacySetting.Version)?.Value ?? 1; decimal version = GetConfig<SkinConfiguration.LegacySetting, decimal>(SkinConfiguration.LegacySetting.Version)?.Value ?? 1;
if (version < 2.3m) if (version < 2.3m)
{ {

View File

@ -57,14 +57,19 @@ namespace osu.Game.Rulesets.Catch.UI
public bool CatchFruitOnPlate { get; set; } = true; public bool CatchFruitOnPlate { get; set; } = true;
/// <summary> /// <summary>
/// The relative space to cover in 1 millisecond. based on 1 game pixel per millisecond as in osu-stable. /// The speed of the catcher when the catcher is dashing.
/// </summary> /// </summary>
public const double BASE_SPEED = 1.0; public const double BASE_DASH_SPEED = 1.0;
/// <summary> /// <summary>
/// The current speed of the catcher. /// The speed of the catcher when the catcher is not dashing.
/// </summary> /// </summary>
public double Speed => (Dashing ? 1 : 0.5) * BASE_SPEED * hyperDashModifier; public const double BASE_WALK_SPEED = 0.5;
/// <summary>
/// The current speed of the catcher with the hyper-dash modifier applied.
/// </summary>
public double Speed => (Dashing ? BASE_DASH_SPEED : BASE_WALK_SPEED) * hyperDashModifier;
/// <summary> /// <summary>
/// The amount by which caught fruit should be scaled down to fit on the plate. /// The amount by which caught fruit should be scaled down to fit on the plate.
@ -226,11 +231,11 @@ namespace osu.Game.Rulesets.Catch.UI
if (result.IsHit && hitObject.HyperDash) if (result.IsHit && hitObject.HyperDash)
{ {
var target = hitObject.HyperDashTarget; var target = hitObject.HyperDashTarget;
var timeDifference = target.StartTime - hitObject.StartTime; double timeDifference = target.StartTime - hitObject.StartTime;
double positionDifference = target.EffectiveX - X; double positionDifference = target.EffectiveX - X;
var velocity = positionDifference / Math.Max(1.0, timeDifference - 1000.0 / 60.0); double velocity = positionDifference / Math.Max(1.0, timeDifference - 1000.0 / 60.0);
SetHyperDashState(Math.Abs(velocity), target.EffectiveX); SetHyperDashState(Math.Abs(velocity) / BASE_DASH_SPEED, target.EffectiveX);
} }
else else
SetHyperDashState(); SetHyperDashState();
@ -266,7 +271,7 @@ namespace osu.Game.Rulesets.Catch.UI
/// <param name="targetPosition">When this catcher crosses this position, this catcher ends hyper-dashing.</param> /// <param name="targetPosition">When this catcher crosses this position, this catcher ends hyper-dashing.</param>
public void SetHyperDashState(double modifier = 1, float targetPosition = -1) public void SetHyperDashState(double modifier = 1, float targetPosition = -1)
{ {
var wasHyperDashing = HyperDashing; bool wasHyperDashing = HyperDashing;
if (modifier <= 1 || X == targetPosition) if (modifier <= 1 || X == targetPosition)
{ {

View File

@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor
protected override SnapResult SnapForBlueprint(PlacementBlueprint blueprint) protected override SnapResult SnapForBlueprint(PlacementBlueprint blueprint)
{ {
var time = column.TimeAtScreenSpacePosition(InputManager.CurrentState.Mouse.Position); double time = column.TimeAtScreenSpacePosition(InputManager.CurrentState.Mouse.Position);
var pos = column.ScreenSpacePositionAtTime(time); var pos = column.ScreenSpacePositionAtTime(time);
return new SnapResult(pos, time, column); return new SnapResult(pos, time, column);

View File

@ -111,7 +111,7 @@ namespace osu.Game.Rulesets.Mania.Tests
public int CompareTo(ConvertValue other) public int CompareTo(ConvertValue other)
{ {
var result = StartTime.CompareTo(other.StartTime); int result = StartTime.CompareTo(other.StartTime);
if (result != 0) if (result != 0)
return result; return result;

View File

@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.Mania.Tests
private IEnumerable<ColumnType> getResults(StageDefinition definition) private IEnumerable<ColumnType> getResults(StageDefinition definition)
{ {
for (var i = 0; i < definition.Columns; i++) for (int i = 0; i < definition.Columns; i++)
yield return definition.GetTypeOfColumn(i); yield return definition.GetTypeOfColumn(i);
} }
} }

View File

@ -42,8 +42,8 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
{ {
IsForCurrentRuleset = beatmap.BeatmapInfo.Ruleset.Equals(ruleset.RulesetInfo); IsForCurrentRuleset = beatmap.BeatmapInfo.Ruleset.Equals(ruleset.RulesetInfo);
var roundedCircleSize = Math.Round(beatmap.Difficulty.CircleSize); double roundedCircleSize = Math.Round(beatmap.Difficulty.CircleSize);
var roundedOverallDifficulty = Math.Round(beatmap.Difficulty.OverallDifficulty); double roundedOverallDifficulty = Math.Round(beatmap.Difficulty.OverallDifficulty);
if (IsForCurrentRuleset) if (IsForCurrentRuleset)
{ {
@ -73,7 +73,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
public static int GetColumnCountForNonConvert(BeatmapInfo beatmapInfo) public static int GetColumnCountForNonConvert(BeatmapInfo beatmapInfo)
{ {
var roundedCircleSize = Math.Round(beatmapInfo.BaseDifficulty.CircleSize); double roundedCircleSize = Math.Round(beatmapInfo.BaseDifficulty.CircleSize);
return (int)Math.Max(1, roundedCircleSize); return (int)Math.Max(1, roundedCircleSize);
} }

View File

@ -493,7 +493,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
if (!(HitObject is IHasPathWithRepeats curveData)) if (!(HitObject is IHasPathWithRepeats curveData))
return null; return null;
var index = SegmentDuration == 0 ? 0 : (time - StartTime) / SegmentDuration; int index = SegmentDuration == 0 ? 0 : (time - StartTime) / SegmentDuration;
// avoid slicing the list & creating copies, if at all possible. // avoid slicing the list & creating copies, if at all possible.
return index == 0 ? curveData.NodeSamples : curveData.NodeSamples.Skip(index).ToList(); return index == 0 ? curveData.NodeSamples : curveData.NodeSamples.Skip(index).ToList();

View File

@ -302,7 +302,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
var pattern = new Pattern(); var pattern = new Pattern();
int noteCount = getRandomNoteCountMirrored(centreProbability, p2, p3, out var addToCentre); int noteCount = getRandomNoteCountMirrored(centreProbability, p2, p3, out bool addToCentre);
int columnLimit = (TotalColumns % 2 == 0 ? TotalColumns : TotalColumns - 1) / 2; int columnLimit = (TotalColumns % 2 == 0 ? TotalColumns : TotalColumns - 1) / 2;
int nextColumn = GetRandomColumn(upperBound: columnLimit); int nextColumn = GetRandomColumn(upperBound: columnLimit);

View File

@ -35,8 +35,8 @@ namespace osu.Game.Rulesets.Mania.Difficulty.Skills
protected override double StrainValueOf(DifficultyHitObject current) protected override double StrainValueOf(DifficultyHitObject current)
{ {
var maniaCurrent = (ManiaDifficultyHitObject)current; var maniaCurrent = (ManiaDifficultyHitObject)current;
var endTime = maniaCurrent.EndTime; double endTime = maniaCurrent.EndTime;
var column = maniaCurrent.BaseObject.Column; int column = maniaCurrent.BaseObject.Column;
double holdFactor = 1.0; // Factor to all additional strains in case something else is held double holdFactor = 1.0; // Factor to all additional strains in case something else is held
double holdAddition = 0; // Addition to the current note in case it's a hold and has to be released awkwardly double holdAddition = 0; // Addition to the current note in case it's a hold and has to be released awkwardly

View File

@ -316,7 +316,7 @@ namespace osu.Game.Rulesets.Mania
case PlayfieldType.Dual: case PlayfieldType.Dual:
{ {
var keys = getDualStageKeyCount(variant); int keys = getDualStageKeyCount(variant);
return $"{keys}K + {keys}K"; return $"{keys}K + {keys}K";
} }
} }

View File

@ -62,9 +62,7 @@ namespace osu.Game.Rulesets.Mania.MathUtils
if (i < j) if (i < j)
{ {
T key = keys[i]; (keys[i], keys[j]) = (keys[j], keys[i]);
keys[i] = keys[j];
keys[j] = key;
} }
i++; i++;
@ -122,7 +120,7 @@ namespace osu.Game.Rulesets.Mania.MathUtils
while (i <= n / 2) while (i <= n / 2)
{ {
var child = 2 * i; int child = 2 * i;
if (child < n && comparer.Compare(keys[lo + child - 1], keys[lo + child]) < 0) if (child < n && comparer.Compare(keys[lo + child - 1], keys[lo + child]) < 0)
{ {
@ -142,11 +140,7 @@ namespace osu.Game.Rulesets.Mania.MathUtils
private static void swap(T[] a, int i, int j) private static void swap(T[] a, int i, int j)
{ {
if (i != j) if (i != j)
{ (a[i], a[j]) = (a[j], a[i]);
T t = a[i];
a[i] = a[j];
a[j] = t;
}
} }
private static void swapIfGreater(T[] keys, IComparer<T> comparer, int a, int b) private static void swapIfGreater(T[] keys, IComparer<T> comparer, int a, int b)
@ -154,11 +148,7 @@ namespace osu.Game.Rulesets.Mania.MathUtils
if (a != b) if (a != b)
{ {
if (comparer.Compare(keys[a], keys[b]) > 0) if (comparer.Compare(keys[a], keys[b]) > 0)
{ (keys[a], keys[b]) = (keys[b], keys[a]);
T key = keys[a];
keys[a] = keys[b];
keys[b] = key;
}
} }
} }
} }

View File

@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Mania.Mods
public void ApplyToBeatmap(IBeatmap beatmap) public void ApplyToBeatmap(IBeatmap beatmap)
{ {
var availableColumns = ((ManiaBeatmap)beatmap).TotalColumns; int availableColumns = ((ManiaBeatmap)beatmap).TotalColumns;
beatmap.HitObjects.OfType<ManiaHitObject>().ForEach(h => h.Column = availableColumns - 1 - h.Column); beatmap.HitObjects.OfType<ManiaHitObject>().ForEach(h => h.Column = availableColumns - 1 - h.Column);
} }

View File

@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Mania.Mods
Seed.Value ??= RNG.Next(); Seed.Value ??= RNG.Next();
var rng = new Random((int)Seed.Value); var rng = new Random((int)Seed.Value);
var availableColumns = ((ManiaBeatmap)beatmap).TotalColumns; int availableColumns = ((ManiaBeatmap)beatmap).TotalColumns;
var shuffledColumns = Enumerable.Range(0, availableColumns).OrderBy(item => rng.Next()).ToList(); var shuffledColumns = Enumerable.Range(0, availableColumns).OrderBy(item => rng.Next()).ToList();
beatmap.HitObjects.OfType<ManiaHitObject>().ForEach(h => h.Column = shuffledColumns[h.Column]); beatmap.HitObjects.OfType<ManiaHitObject>().ForEach(h => h.Column = shuffledColumns[h.Column]);

View File

@ -97,7 +97,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
if (Time.Current < HitObject.StartTime) if (Time.Current < HitObject.StartTime)
return; return;
var startTime = holdStartTime?.Invoke(); double? startTime = holdStartTime?.Invoke();
if (startTime == null || startTime > HitObject.StartTime) if (startTime == null || startTime > HitObject.StartTime)
ApplyResult(r => r.Type = r.Judgement.MinResult); ApplyResult(r => r.Type = r.Judgement.MinResult);

View File

@ -75,7 +75,7 @@ namespace osu.Game.Rulesets.Mania.Replays
{ {
var currentObject = Beatmap.HitObjects[i]; var currentObject = Beatmap.HitObjects[i];
var nextObjectInColumn = GetNextObject(i); // Get the next object that requires pressing the same button var nextObjectInColumn = GetNextObject(i); // Get the next object that requires pressing the same button
var releaseTime = calculateReleaseTime(currentObject, nextObjectInColumn); double releaseTime = calculateReleaseTime(currentObject, nextObjectInColumn);
yield return new HitPoint { Time = currentObject.StartTime, Column = currentObject.Column }; yield return new HitPoint { Time = currentObject.StartTime, Column = currentObject.Column };

View File

@ -98,7 +98,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
float rightLineWidth = skin.GetManiaSkinConfig<float>(LegacyManiaSkinConfigurationLookups.RightLineWidth, columnIndex)?.Value ?? 1; float rightLineWidth = skin.GetManiaSkinConfig<float>(LegacyManiaSkinConfigurationLookups.RightLineWidth, columnIndex)?.Value ?? 1;
bool hasLeftLine = leftLineWidth > 0; bool hasLeftLine = leftLineWidth > 0;
bool hasRightLine = rightLineWidth > 0 && skin.GetConfig<LegacySkinConfiguration.LegacySetting, decimal>(LegacySkinConfiguration.LegacySetting.Version)?.Value >= 2.4m bool hasRightLine = rightLineWidth > 0 && skin.GetConfig<SkinConfiguration.LegacySetting, decimal>(SkinConfiguration.LegacySetting.Version)?.Value >= 2.4m
|| isLastColumn; || isLastColumn;
Color4 lineColour = skin.GetManiaSkinConfig<Color4>(LegacyManiaSkinConfigurationLookups.ColumnLineColour, columnIndex)?.Value ?? Color4.White; Color4 lineColour = skin.GetManiaSkinConfig<Color4>(LegacyManiaSkinConfigurationLookups.ColumnLineColour, columnIndex)?.Value ?? Color4.White;

View File

@ -63,10 +63,10 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
{ {
this.beatmap = (ManiaBeatmap)beatmap; this.beatmap = (ManiaBeatmap)beatmap;
isLegacySkin = new Lazy<bool>(() => GetConfig<LegacySkinConfiguration.LegacySetting, decimal>(LegacySkinConfiguration.LegacySetting.Version) != null); isLegacySkin = new Lazy<bool>(() => GetConfig<SkinConfiguration.LegacySetting, decimal>(SkinConfiguration.LegacySetting.Version) != null);
hasKeyTexture = new Lazy<bool>(() => hasKeyTexture = new Lazy<bool>(() =>
{ {
var keyImage = this.GetManiaSkinConfig<string>(LegacyManiaSkinConfigurationLookups.KeyImage, 0)?.Value ?? "mania-key1"; string keyImage = this.GetManiaSkinConfig<string>(LegacyManiaSkinConfigurationLookups.KeyImage, 0)?.Value ?? "mania-key1";
return this.GetAnimation(keyImage, true, true) != null; return this.GetAnimation(keyImage, true, true) != null;
}); });
} }

View File

@ -0,0 +1,150 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Utils;
using osu.Framework.Testing;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Timing;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Osu.Mods;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Objects.Drawables;
using osuTK;
namespace osu.Game.Rulesets.Osu.Tests.Mods
{
public class TestSceneOsuModNoScope : OsuModTestScene
{
[Test]
public void TestVisibleDuringBreak()
{
CreateModTest(new ModTestData
{
Mod = new OsuModNoScope
{
HiddenComboCount = { Value = 0 },
},
Autoplay = true,
PassCondition = () => true,
Beatmap = new Beatmap
{
HitObjects = new List<HitObject>
{
new HitCircle
{
Position = new Vector2(300, 192),
StartTime = 1000,
},
new HitCircle
{
Position = new Vector2(300, 192),
StartTime = 5000,
}
},
Breaks = new List<BreakPeriod>
{
new BreakPeriod(2000, 4000),
}
}
});
AddUntilStep("wait for cursor to hide", () => cursorAlphaAlmostEquals(0));
AddUntilStep("wait for start of break", isBreak);
AddUntilStep("wait for cursor to show", () => cursorAlphaAlmostEquals(1));
AddUntilStep("wait for end of break", () => !isBreak());
AddUntilStep("wait for cursor to hide", () => cursorAlphaAlmostEquals(0));
}
[Test]
public void TestVisibleDuringSpinner()
{
CreateModTest(new ModTestData
{
Mod = new OsuModNoScope
{
HiddenComboCount = { Value = 0 },
},
Autoplay = true,
PassCondition = () => true,
Beatmap = new Beatmap
{
HitObjects = new List<HitObject>
{
new HitCircle
{
Position = new Vector2(300, 192),
StartTime = 1000,
},
new Spinner
{
Position = new Vector2(256, 192),
StartTime = 2000,
Duration = 2000,
},
new HitCircle
{
Position = new Vector2(300, 192),
StartTime = 5000,
}
}
}
});
AddUntilStep("wait for cursor to hide", () => cursorAlphaAlmostEquals(0));
AddUntilStep("wait for start of spinner", isSpinning);
AddUntilStep("wait for cursor to show", () => cursorAlphaAlmostEquals(1));
AddUntilStep("wait for end of spinner", () => !isSpinning());
AddUntilStep("wait for cursor to hide", () => cursorAlphaAlmostEquals(0));
}
[Test]
public void TestVisibleAfterComboBreak()
{
CreateModTest(new ModTestData
{
Mod = new OsuModNoScope
{
HiddenComboCount = { Value = 2 },
},
Autoplay = true,
PassCondition = () => true,
Beatmap = new Beatmap
{
HitObjects = new List<HitObject>
{
new HitCircle
{
Position = new Vector2(100, 192),
StartTime = 1000,
},
new HitCircle
{
Position = new Vector2(150, 192),
StartTime = 3000,
},
new HitCircle
{
Position = new Vector2(200, 192),
StartTime = 5000,
},
}
}
});
AddAssert("cursor must start visible", () => cursorAlphaAlmostEquals(1));
AddUntilStep("wait for combo", () => Player.ScoreProcessor.Combo.Value >= 2);
AddAssert("cursor must dim after combo", () => !cursorAlphaAlmostEquals(1));
AddStep("break combo", () => Player.ScoreProcessor.Combo.Set(0));
AddUntilStep("wait for cursor to show", () => cursorAlphaAlmostEquals(1));
}
private bool isSpinning() => Player.ChildrenOfType<DrawableSpinner>().SingleOrDefault()?.Progress > 0;
private bool isBreak() => Player.IsBreakTime.Value;
private bool cursorAlphaAlmostEquals(float alpha) => Precision.AlmostEquals(Player.DrawableRuleset.Cursor.Alpha, alpha);
}
}

View File

@ -97,7 +97,7 @@ namespace osu.Game.Rulesets.Osu.Tests
private void scheduleHit() => AddStep("schedule action", () => private void scheduleHit() => AddStep("schedule action", () =>
{ {
var delay = hitCircle.StartTime - hitCircle.HitWindows.WindowFor(HitResult.Great) - Time.Current; double delay = hitCircle.StartTime - hitCircle.HitWindows.WindowFor(HitResult.Great) - Time.Current;
Scheduler.AddDelayed(() => hitAreaReceptor.OnPressed(new KeyBindingPressEvent<OsuAction>(GetContainingInputManager().CurrentState, OsuAction.LeftButton)), delay); Scheduler.AddDelayed(() => hitAreaReceptor.OnPressed(new KeyBindingPressEvent<OsuAction>(GetContainingInputManager().CurrentState, OsuAction.LeftButton)), delay);
}); });
} }

View File

@ -148,7 +148,7 @@ namespace osu.Game.Rulesets.Osu.Tests
AddAssert("player score matching expected bonus score", () => AddAssert("player score matching expected bonus score", () =>
{ {
// multipled by 2 to nullify the score multiplier. (autoplay mod selected) // multipled by 2 to nullify the score multiplier. (autoplay mod selected)
var totalScore = ((ScoreExposedPlayer)Player).ScoreProcessor.TotalScore.Value * 2; double totalScore = ((ScoreExposedPlayer)Player).ScoreProcessor.TotalScore.Value * 2;
return totalScore == (int)(drawableSpinner.Result.RateAdjustedRotation / 360) * new SpinnerTick().CreateJudgement().MaxNumericResult; return totalScore == (int)(drawableSpinner.Result.RateAdjustedRotation / 360) * new SpinnerTick().CreateJudgement().MaxNumericResult;
}); });

View File

@ -123,7 +123,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
// Skip the head circle // Skip the head circle
var scoringTimes = slider.NestedHitObjects.Skip(1).Select(t => t.StartTime); var scoringTimes = slider.NestedHitObjects.Skip(1).Select(t => t.StartTime);
foreach (var time in scoringTimes) foreach (double time in scoringTimes)
computeVertex(time); computeVertex(time);
} }

View File

@ -44,7 +44,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
{ {
const double scale = 90; const double scale = 90;
var angleBonus = Math.Sqrt( double angleBonus = Math.Sqrt(
Math.Max(osuPrevious.JumpDistance - scale, 0) Math.Max(osuPrevious.JumpDistance - scale, 0)
* Math.Pow(Math.Sin(osuCurrent.Angle.Value - angle_bonus_begin), 2) * Math.Pow(Math.Sin(osuCurrent.Angle.Value - angle_bonus_begin), 2)
* Math.Max(osuCurrent.JumpDistance - scale, 0)); * Math.Max(osuCurrent.JumpDistance - scale, 0));

View File

@ -184,7 +184,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
{ {
Vector2[] oldControlPoints = slider.Path.ControlPoints.Select(cp => cp.Position).ToArray(); Vector2[] oldControlPoints = slider.Path.ControlPoints.Select(cp => cp.Position).ToArray();
var oldPosition = slider.Position; var oldPosition = slider.Position;
var oldStartTime = slider.StartTime; double oldStartTime = slider.StartTime;
if (ControlPoint == slider.Path.ControlPoints[0]) if (ControlPoint == slider.Path.ControlPoints[0])
{ {
@ -205,7 +205,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
if (!slider.Path.HasValidLength) if (!slider.Path.HasValidLength)
{ {
for (var i = 0; i < slider.Path.ControlPoints.Count; i++) for (int i = 0; i < slider.Path.ControlPoints.Count; i++)
slider.Path.ControlPoints[i].Position = oldControlPoints[i]; slider.Path.ControlPoints[i].Position = oldControlPoints[i];
slider.Position = oldPosition; slider.Position = oldPosition;

View File

@ -47,14 +47,14 @@ namespace osu.Game.Rulesets.Osu.Edit.Checks
if (!(hitObjects[i + 1] is OsuHitObject nextHitObject) || nextHitObject is Spinner) if (!(hitObjects[i + 1] is OsuHitObject nextHitObject) || nextHitObject is Spinner)
continue; continue;
var deltaTime = nextHitObject.StartTime - hitObject.GetEndTime(); double deltaTime = nextHitObject.StartTime - hitObject.GetEndTime();
if (deltaTime >= hitObject.TimeFadeIn + hitObject.TimePreempt) if (deltaTime >= hitObject.TimeFadeIn + hitObject.TimePreempt)
// The objects are not visible at the same time (without mods), hence skipping. // The objects are not visible at the same time (without mods), hence skipping.
continue; continue;
var distanceSq = (hitObject.StackedEndPosition - nextHitObject.StackedPosition).LengthSquared; float distanceSq = (hitObject.StackedEndPosition - nextHitObject.StackedPosition).LengthSquared;
var diameter = (hitObject.Radius - overlap_leniency) * 2; double diameter = (hitObject.Radius - overlap_leniency) * 2;
var diameterSq = diameter * diameter; double diameterSq = diameter * diameter;
bool areOverlapping = distanceSq < diameterSq; bool areOverlapping = distanceSq < diameterSq;

View File

@ -88,21 +88,21 @@ namespace osu.Game.Rulesets.Osu.Edit.Checks
if (!(hitObjects[i + 1] is OsuHitObject nextHitObject) || nextHitObject is Spinner) if (!(hitObjects[i + 1] is OsuHitObject nextHitObject) || nextHitObject is Spinner)
continue; continue;
var deltaTime = nextHitObject.StartTime - hitObject.GetEndTime(); double deltaTime = nextHitObject.StartTime - hitObject.GetEndTime();
// Ignore objects that are far enough apart in time to not be considered the same pattern. // Ignore objects that are far enough apart in time to not be considered the same pattern.
if (deltaTime > pattern_lifetime) if (deltaTime > pattern_lifetime)
continue; continue;
// Relying on FastInvSqrt is probably good enough here. We'll be taking the difference between distances later, hence square not being sufficient. // Relying on FastInvSqrt is probably good enough here. We'll be taking the difference between distances later, hence square not being sufficient.
var distance = (hitObject.StackedEndPosition - nextHitObject.StackedPosition).LengthFast; float distance = (hitObject.StackedEndPosition - nextHitObject.StackedPosition).LengthFast;
// Ignore stacks and half-stacks, as these are close enough to where they can't be confused for being time-distanced. // Ignore stacks and half-stacks, as these are close enough to where they can't be confused for being time-distanced.
if (distance < stack_leniency) if (distance < stack_leniency)
continue; continue;
var observedTimeDistance = new ObservedTimeDistance(nextHitObject.StartTime, deltaTime, distance); var observedTimeDistance = new ObservedTimeDistance(nextHitObject.StartTime, deltaTime, distance);
var expectedDistance = getExpectedDistance(prevObservedTimeDistances, observedTimeDistance); double expectedDistance = getExpectedDistance(prevObservedTimeDistances, observedTimeDistance);
if (expectedDistance == 0) if (expectedDistance == 0)
{ {
@ -125,7 +125,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Checks
private double getExpectedDistance(IEnumerable<ObservedTimeDistance> prevObservedTimeDistances, ObservedTimeDistance observedTimeDistance) private double getExpectedDistance(IEnumerable<ObservedTimeDistance> prevObservedTimeDistances, ObservedTimeDistance observedTimeDistance)
{ {
var observations = prevObservedTimeDistances.Count(); int observations = prevObservedTimeDistances.Count();
int count = 0; int count = 0;
double sum = 0; double sum = 0;

View File

@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Osu.Edit
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {
var gridSizeIndex = Array.IndexOf(grid_sizes, editorBeatmap.BeatmapInfo.GridSize); int gridSizeIndex = Array.IndexOf(grid_sizes, editorBeatmap.BeatmapInfo.GridSize);
if (gridSizeIndex >= 0) if (gridSizeIndex >= 0)
currentGridSizeIndex = gridSizeIndex; currentGridSizeIndex = gridSizeIndex;
updateSpacing(); updateSpacing();

View File

@ -170,7 +170,7 @@ namespace osu.Game.Rulesets.Osu.Mods
base.LoadComplete(); base.LoadComplete();
var firstObj = beatmap.HitObjects[0]; var firstObj = beatmap.HitObjects[0];
var startDelay = firstObj.StartTime - firstObj.TimePreempt; double startDelay = firstObj.StartTime - firstObj.TimePreempt;
using (BeginAbsoluteSequence(startDelay + break_close_late)) using (BeginAbsoluteSequence(startDelay + break_close_late))
leaveBreak(); leaveBreak();

View File

@ -155,11 +155,11 @@ namespace osu.Game.Rulesets.Osu.Mods
static (double fadeStartTime, double fadeDuration) getParameters(OsuHitObject hitObject) static (double fadeStartTime, double fadeDuration) getParameters(OsuHitObject hitObject)
{ {
var fadeOutStartTime = hitObject.StartTime - hitObject.TimePreempt + hitObject.TimeFadeIn; double fadeOutStartTime = hitObject.StartTime - hitObject.TimePreempt + hitObject.TimeFadeIn;
var fadeOutDuration = hitObject.TimePreempt * fade_out_duration_multiplier; double fadeOutDuration = hitObject.TimePreempt * fade_out_duration_multiplier;
// new duration from completed fade in to end (before fading out) // new duration from completed fade in to end (before fading out)
var longFadeDuration = hitObject.GetEndTime() - fadeOutStartTime; double longFadeDuration = hitObject.GetEndTime() - fadeOutStartTime;
switch (hitObject) switch (hitObject)
{ {
@ -167,7 +167,7 @@ namespace osu.Game.Rulesets.Osu.Mods
return (fadeOutStartTime, longFadeDuration); return (fadeOutStartTime, longFadeDuration);
case SliderTick _: case SliderTick _:
var tickFadeOutDuration = Math.Min(hitObject.TimePreempt - DrawableSliderTick.ANIM_DURATION, 1000); double tickFadeOutDuration = Math.Min(hitObject.TimePreempt - DrawableSliderTick.ANIM_DURATION, 1000);
return (hitObject.StartTime - tickFadeOutDuration, tickFadeOutDuration); return (hitObject.StartTime - tickFadeOutDuration, tickFadeOutDuration);
case Spinner _: case Spinner _:

View File

@ -2,22 +2,27 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System; using System;
using osu.Game.Rulesets.UI; using System.Linq;
using osu.Game.Rulesets.Mods; using osu.Framework.Bindables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Framework.Bindables;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Framework.Utils; using osu.Framework.Utils;
using osu.Game.Graphics.UserInterface; using osu.Game.Beatmaps;
using osu.Game.Configuration; using osu.Game.Configuration;
using osu.Game.Graphics.UserInterface;
using osu.Game.Overlays.Settings; using osu.Game.Overlays.Settings;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.UI;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Scoring; using osu.Game.Scoring;
using osu.Game.Screens.Play;
using osu.Game.Utils;
namespace osu.Game.Rulesets.Osu.Mods namespace osu.Game.Rulesets.Osu.Mods
{ {
public class OsuModNoScope : Mod, IUpdatableByPlayfield, IApplicableToScoreProcessor public class OsuModNoScope : Mod, IUpdatableByPlayfield, IApplicableToScoreProcessor, IApplicableToPlayer, IApplicableToBeatmap
{ {
/// <summary> /// <summary>
/// Slightly higher than the cutoff for <see cref="Drawable.IsPresent"/>. /// Slightly higher than the cutoff for <see cref="Drawable.IsPresent"/>.
@ -34,8 +39,10 @@ namespace osu.Game.Rulesets.Osu.Mods
public override double ScoreMultiplier => 1; public override double ScoreMultiplier => 1;
private BindableNumber<int> currentCombo; private BindableNumber<int> currentCombo;
private IBindable<bool> isBreakTime;
private PeriodTracker spinnerPeriods;
private float targetAlpha; private float comboBasedAlpha;
[SettingSource( [SettingSource(
"Hidden at combo", "Hidden at combo",
@ -52,6 +59,16 @@ namespace osu.Game.Rulesets.Osu.Mods
public ScoreRank AdjustRank(ScoreRank rank, double accuracy) => rank; public ScoreRank AdjustRank(ScoreRank rank, double accuracy) => rank;
public void ApplyToPlayer(Player player)
{
isBreakTime = player.IsBreakTime.GetBoundCopy();
}
public void ApplyToBeatmap(IBeatmap beatmap)
{
spinnerPeriods = new PeriodTracker(beatmap.HitObjects.OfType<Spinner>().Select(b => new Period(b.StartTime - transition_duration, b.EndTime)));
}
public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor)
{ {
if (HiddenComboCount.Value == 0) return; if (HiddenComboCount.Value == 0) return;
@ -59,12 +76,14 @@ namespace osu.Game.Rulesets.Osu.Mods
currentCombo = scoreProcessor.Combo.GetBoundCopy(); currentCombo = scoreProcessor.Combo.GetBoundCopy();
currentCombo.BindValueChanged(combo => currentCombo.BindValueChanged(combo =>
{ {
targetAlpha = Math.Max(min_alpha, 1 - (float)combo.NewValue / HiddenComboCount.Value); comboBasedAlpha = Math.Max(min_alpha, 1 - (float)combo.NewValue / HiddenComboCount.Value);
}, true); }, true);
} }
public virtual void Update(Playfield playfield) public virtual void Update(Playfield playfield)
{ {
bool shouldAlwaysShowCursor = isBreakTime.Value || spinnerPeriods.IsInAny(playfield.Clock.CurrentTime);
float targetAlpha = shouldAlwaysShowCursor ? 1 : comboBasedAlpha;
playfield.Cursor.Alpha = (float)Interpolation.Lerp(playfield.Cursor.Alpha, targetAlpha, Math.Clamp(playfield.Time.Elapsed / transition_duration, 0, 1)); playfield.Cursor.Alpha = (float)Interpolation.Lerp(playfield.Cursor.Alpha, targetAlpha, Math.Clamp(playfield.Time.Elapsed / transition_duration, 0, 1));
} }
} }

View File

@ -124,7 +124,7 @@ namespace osu.Game.Rulesets.Osu.Mods
// to allow jumps and prevent too sharp turns during streams. // to allow jumps and prevent too sharp turns during streams.
// Allow maximum jump angle when jump distance is more than half of playfield diagonal length // Allow maximum jump angle when jump distance is more than half of playfield diagonal length
var randomAngleRad = rateOfChangeMultiplier * 2 * Math.PI * Math.Min(1f, distanceToPrev / (playfield_diagonal * 0.5f)); double randomAngleRad = rateOfChangeMultiplier * 2 * Math.PI * Math.Min(1f, distanceToPrev / (playfield_diagonal * 0.5f));
current.AngleRad = (float)randomAngleRad + previous.AngleRad; current.AngleRad = (float)randomAngleRad + previous.AngleRad;
if (current.AngleRad < 0) if (current.AngleRad < 0)
@ -171,11 +171,11 @@ namespace osu.Game.Rulesets.Osu.Mods
// Clamp slider position to the placement area // Clamp slider position to the placement area
// If the slider is larger than the playfield, force it to stay at the original position // If the slider is larger than the playfield, force it to stay at the original position
var newX = possibleMovementBounds.Width < 0 float newX = possibleMovementBounds.Width < 0
? objectInfo.PositionOriginal.X ? objectInfo.PositionOriginal.X
: Math.Clamp(previousPosition.X, possibleMovementBounds.Left, possibleMovementBounds.Right); : Math.Clamp(previousPosition.X, possibleMovementBounds.Left, possibleMovementBounds.Right);
var newY = possibleMovementBounds.Height < 0 float newY = possibleMovementBounds.Height < 0
? objectInfo.PositionOriginal.Y ? objectInfo.PositionOriginal.Y
: Math.Clamp(previousPosition.Y, possibleMovementBounds.Top, possibleMovementBounds.Bottom); : Math.Clamp(previousPosition.Y, possibleMovementBounds.Top, possibleMovementBounds.Bottom);
@ -235,7 +235,7 @@ namespace osu.Game.Rulesets.Osu.Mods
} }
// Take the circle radius into account. // Take the circle radius into account.
var radius = (float)slider.Radius; float radius = (float)slider.Radius;
minX -= radius; minX -= radius;
minY -= radius; minY -= radius;

View File

@ -44,7 +44,7 @@ namespace osu.Game.Rulesets.Osu.Mods
// because the spinner is under the gameplay clock, it is affected by rate adjustments on the track; // because the spinner is under the gameplay clock, it is affected by rate adjustments on the track;
// for that reason using ElapsedFrameTime directly leads to fewer SPM with Half Time and more SPM with Double Time. // for that reason using ElapsedFrameTime directly leads to fewer SPM with Half Time and more SPM with Double Time.
// for spinners we want the real (wall clock) elapsed time; to achieve that, unapply the clock rate locally here. // for spinners we want the real (wall clock) elapsed time; to achieve that, unapply the clock rate locally here.
var rateIndependentElapsedTime = spinner.Clock.ElapsedFrameTime / spinner.Clock.Rate; double rateIndependentElapsedTime = spinner.Clock.ElapsedFrameTime / spinner.Clock.Rate;
spinner.RotationTracker.AddRotation(MathUtils.RadiansToDegrees((float)rateIndependentElapsedTime * 0.03f)); spinner.RotationTracker.AddRotation(MathUtils.RadiansToDegrees((float)rateIndependentElapsedTime * 0.03f));
} }
} }

View File

@ -193,8 +193,8 @@ namespace osu.Game.Rulesets.Osu.Mods
private IEnumerable<double> generateBeats(IBeatmap beatmap) private IEnumerable<double> generateBeats(IBeatmap beatmap)
{ {
var startTime = originalHitObjects.First().StartTime; double startTime = originalHitObjects.First().StartTime;
var endTime = originalHitObjects.Last().GetEndTime(); double endTime = originalHitObjects.Last().GetEndTime();
var beats = beatmap.ControlPointInfo.TimingPoints var beats = beatmap.ControlPointInfo.TimingPoints
// Ignore timing points after endTime // Ignore timing points after endTime
@ -208,9 +208,9 @@ namespace osu.Game.Rulesets.Osu.Mods
.ToList(); .ToList();
// Remove beats that are too close to the next one (e.g. due to timing point changes) // Remove beats that are too close to the next one (e.g. due to timing point changes)
for (var i = beats.Count - 2; i >= 0; i--) for (int i = beats.Count - 2; i >= 0; i--)
{ {
var beat = beats[i]; double beat = beats[i];
if (!definitelyBigger(beats[i + 1] - beat, beatmap.ControlPointInfo.TimingPointAt(beat).BeatLength / 2)) if (!definitelyBigger(beats[i + 1] - beat, beatmap.ControlPointInfo.TimingPointAt(beat).BeatLength / 2))
beats.RemoveAt(i); beats.RemoveAt(i);
@ -250,13 +250,13 @@ namespace osu.Game.Rulesets.Osu.Mods
// Other kinds of combo info are also added in the process // Other kinds of combo info are also added in the process
var combos = hitObjects.GroupBy(x => x.ComboIndex).ToList(); var combos = hitObjects.GroupBy(x => x.ComboIndex).ToList();
for (var i = 0; i < combos.Count; i++) for (int i = 0; i < combos.Count; i++)
{ {
var group = combos[i].ToList(); var group = combos[i].ToList();
group.First().NewCombo = true; group.First().NewCombo = true;
group.Last().LastInCombo = true; group.Last().LastInCombo = true;
for (var j = 0; j < group.Count; j++) for (int j = 0; j < group.Count; j++)
{ {
var x = group[j]; var x = group[j];
x.ComboIndex = i; x.ComboIndex = i;
@ -273,17 +273,17 @@ namespace osu.Game.Rulesets.Osu.Mods
const float two_pi = MathF.PI * 2; const float two_pi = MathF.PI * 2;
var direction = two_pi * nextSingle(); float direction = two_pi * nextSingle();
var maxComboIndex = hitObjects.Last().ComboIndex; int maxComboIndex = hitObjects.Last().ComboIndex;
for (var i = 0; i < hitObjects.Count; i++) for (int i = 0; i < hitObjects.Count; i++)
{ {
var obj = hitObjects[i]; var obj = hitObjects[i];
var lastPos = i == 0 var lastPos = i == 0
? Vector2.Divide(OsuPlayfield.BASE_SIZE, 2) ? Vector2.Divide(OsuPlayfield.BASE_SIZE, 2)
: hitObjects[i - 1].Position; : hitObjects[i - 1].Position;
var distance = maxComboIndex == 0 float distance = maxComboIndex == 0
? (float)obj.Radius ? (float)obj.Radius
: mapRange(obj.ComboIndex, 0, maxComboIndex, (float)obj.Radius, max_base_distance); : mapRange(obj.ComboIndex, 0, maxComboIndex, (float)obj.Radius, max_base_distance);
if (obj.NewCombo) distance *= 1.5f; if (obj.NewCombo) distance *= 1.5f;
@ -292,7 +292,7 @@ namespace osu.Game.Rulesets.Osu.Mods
// Attempt to place the circle at a place that does not overlap with previous ones // Attempt to place the circle at a place that does not overlap with previous ones
var tryCount = 0; int tryCount = 0;
// for checking overlap // for checking overlap
var precedingObjects = hitObjects.SkipLast(hitObjects.Count - i).TakeLast(overlap_check_count).ToList(); var precedingObjects = hitObjects.SkipLast(hitObjects.Count - i).TakeLast(overlap_check_count).ToList();
@ -363,7 +363,7 @@ namespace osu.Game.Rulesets.Osu.Mods
{ {
var beats = new List<double>(); var beats = new List<double>();
int i = 0; int i = 0;
var currentTime = timingPoint.Time; double currentTime = timingPoint.Time;
while (!definitelyBigger(currentTime, mapEndTime) && controlPointInfo.TimingPointAt(currentTime) == timingPoint) while (!definitelyBigger(currentTime, mapEndTime) && controlPointInfo.TimingPointAt(currentTime) == timingPoint)
{ {
@ -377,7 +377,7 @@ namespace osu.Game.Rulesets.Osu.Mods
private OsuHitObject getClosestHitObject(List<OsuHitObject> hitObjects, double time) private OsuHitObject getClosestHitObject(List<OsuHitObject> hitObjects, double time)
{ {
var precedingIndex = hitObjects.FindLastIndex(h => h.StartTime < time); int precedingIndex = hitObjects.FindLastIndex(h => h.StartTime < time);
if (precedingIndex == hitObjects.Count - 1) return hitObjects[precedingIndex]; if (precedingIndex == hitObjects.Count - 1) return hitObjects[precedingIndex];
@ -457,7 +457,7 @@ namespace osu.Game.Rulesets.Osu.Mods
private void clampToPlayfield(OsuHitObject obj) private void clampToPlayfield(OsuHitObject obj)
{ {
var position = obj.Position; var position = obj.Position;
var radius = (float)obj.Radius; float radius = (float)obj.Radius;
if (position.Y < radius) if (position.Y < radius)
position.Y = radius; position.Y = radius;

View File

@ -67,7 +67,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
Vector2 pointStartPosition = startPosition + (fraction - 0.1f) * distanceVector; Vector2 pointStartPosition = startPosition + (fraction - 0.1f) * distanceVector;
Vector2 pointEndPosition = startPosition + fraction * distanceVector; Vector2 pointEndPosition = startPosition + fraction * distanceVector;
GetFadeTimes(start, end, (float)d / distance, out var fadeInTime, out var fadeOutTime); GetFadeTimes(start, end, (float)d / distance, out double fadeInTime, out double fadeOutTime);
FollowPoint fp; FollowPoint fp;

View File

@ -93,7 +93,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
// The lifetime start will match the fade-in time of the first follow point. // The lifetime start will match the fade-in time of the first follow point.
float fraction = (int)(FollowPointConnection.SPACING * 1.5) / distanceVector.Length; float fraction = (int)(FollowPointConnection.SPACING * 1.5) / distanceVector.Length;
FollowPointConnection.GetFadeTimes(Start, End, fraction, out var fadeInTime, out _); FollowPointConnection.GetFadeTimes(Start, End, fraction, out double fadeInTime, out _);
LifetimeStart = fadeInTime; LifetimeStart = fadeInTime;
LifetimeEnd = double.MaxValue; // This will be set by the connection. LifetimeEnd = double.MaxValue; // This will be set by the connection.

View File

@ -56,7 +56,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
{ {
var newEntry = new FollowPointLifetimeEntry(hitObject); var newEntry = new FollowPointLifetimeEntry(hitObject);
var index = lifetimeEntries.AddInPlace(newEntry, Comparer<FollowPointLifetimeEntry>.Create((e1, e2) => int index = lifetimeEntries.AddInPlace(newEntry, Comparer<FollowPointLifetimeEntry>.Create((e1, e2) =>
{ {
int comp = e1.Start.StartTime.CompareTo(e2.Start.StartTime); int comp = e1.Start.StartTime.CompareTo(e2.Start.StartTime);

View File

@ -70,8 +70,8 @@ namespace osu.Game.Rulesets.Osu.Skinning.Default
Slider slider = drawableSlider.HitObject; Slider slider = drawableSlider.HitObject;
var span = slider.SpanAt(completionProgress); int span = slider.SpanAt(completionProgress);
var spanProgress = slider.ProgressAt(completionProgress); double spanProgress = slider.ProgressAt(completionProgress);
double start = 0; double start = 0;
double end = SnakingIn.Value ? Math.Clamp((Time.Current - (slider.StartTime - slider.TimePreempt)) / (slider.TimePreempt / 3), 0, 1) : 1; double end = SnakingIn.Value ? Math.Clamp((Time.Current - (slider.StartTime - slider.TimePreempt)) / (slider.TimePreempt / 3), 0, 1) : 1;
@ -110,8 +110,8 @@ namespace osu.Game.Rulesets.Osu.Skinning.Default
snakedPosition = Path.PositionInBoundingBox(Vector2.Zero); snakedPosition = Path.PositionInBoundingBox(Vector2.Zero);
snakedPathOffset = Path.PositionInBoundingBox(Path.Vertices[0]); snakedPathOffset = Path.PositionInBoundingBox(Path.Vertices[0]);
var lastSnakedStart = SnakedStart ?? 0; double lastSnakedStart = SnakedStart ?? 0;
var lastSnakedEnd = SnakedEnd ?? 0; double lastSnakedEnd = SnakedEnd ?? 0;
SnakedStart = null; SnakedStart = null;
SnakedEnd = null; SnakedEnd = null;

View File

@ -62,9 +62,9 @@ namespace osu.Game.Rulesets.Osu.Skinning.Default
protected override void Update() protected override void Update()
{ {
base.Update(); base.Update();
var thisAngle = -MathUtils.RadiansToDegrees(MathF.Atan2(mousePosition.X - DrawSize.X / 2, mousePosition.Y - DrawSize.Y / 2)); float thisAngle = -MathUtils.RadiansToDegrees(MathF.Atan2(mousePosition.X - DrawSize.X / 2, mousePosition.Y - DrawSize.Y / 2));
var delta = thisAngle - lastAngle; float delta = thisAngle - lastAngle;
if (Tracking) if (Tracking)
AddRotation(delta); AddRotation(delta);

View File

@ -14,7 +14,6 @@ using osu.Game.Rulesets.Osu.Objects.Drawables;
using osu.Game.Skinning; using osu.Game.Skinning;
using osuTK; using osuTK;
using osuTK.Graphics; using osuTK.Graphics;
using static osu.Game.Skinning.LegacySkinConfiguration;
namespace osu.Game.Rulesets.Osu.Skinning.Legacy namespace osu.Game.Rulesets.Osu.Skinning.Legacy
{ {
@ -158,7 +157,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
if (hasNumber) if (hasNumber)
{ {
var legacyVersion = skin.GetConfig<LegacySetting, decimal>(LegacySetting.Version)?.Value; decimal? legacyVersion = skin.GetConfig<SkinConfiguration.LegacySetting, decimal>(SkinConfiguration.LegacySetting.Version)?.Value;
if (legacyVersion >= 2.0m) if (legacyVersion >= 2.0m)
// legacy skins of version 2.0 and newer only apply very short fade out to the number piece. // legacy skins of version 2.0 and newer only apply very short fade out to the number piece.

View File

@ -103,7 +103,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
// careful: need to call this exactly once for all calculations in a frame // careful: need to call this exactly once for all calculations in a frame
// as the function has a random factor in it // as the function has a random factor in it
var metreHeight = getMetreHeight(DrawableSpinner.Progress); float metreHeight = getMetreHeight(DrawableSpinner.Progress);
// hack to make the metre blink up from below than down from above. // hack to make the metre blink up from below than down from above.
// move down the container to be able to apply masking for the metre, // move down the container to be able to apply masking for the metre,

View File

@ -216,7 +216,7 @@ namespace osu.Game.Rulesets.Osu.Statistics
// Likewise sin(pi/2)=1 and sin(3pi/2)=-1, whereas we actually want these values to appear on the bottom/top respectively, so the y-coordinate also needs to be inverted. // Likewise sin(pi/2)=1 and sin(3pi/2)=-1, whereas we actually want these values to appear on the bottom/top respectively, so the y-coordinate also needs to be inverted.
// //
// We also need to apply the anti-clockwise rotation. // We also need to apply the anti-clockwise rotation.
var rotatedAngle = finalAngle - MathUtils.DegreesToRadians(rotation); double rotatedAngle = finalAngle - MathUtils.DegreesToRadians(rotation);
var rotatedCoordinate = -1 * new Vector2((float)Math.Cos(rotatedAngle), (float)Math.Sin(rotatedAngle)); var rotatedCoordinate = -1 * new Vector2((float)Math.Cos(rotatedAngle), (float)Math.Sin(rotatedAngle));
Vector2 localCentre = new Vector2(points_per_dimension - 1) / 2; Vector2 localCentre = new Vector2(points_per_dimension - 1) / 2;

View File

@ -40,7 +40,7 @@ namespace osu.Game.Rulesets.Osu.Utils
/// <returns>The new position of the hit object, relative to the previous one.</returns> /// <returns>The new position of the hit object, relative to the previous one.</returns>
public static Vector2 RotateAwayFromEdge(Vector2 prevObjectPos, Vector2 posRelativeToPrev, float rotationRatio = 0.5f) public static Vector2 RotateAwayFromEdge(Vector2 prevObjectPos, Vector2 posRelativeToPrev, float rotationRatio = 0.5f)
{ {
var relativeRotationDistance = 0f; float relativeRotationDistance = 0f;
if (prevObjectPos.X < playfield_middle.X) if (prevObjectPos.X < playfield_middle.X)
{ {
@ -88,16 +88,16 @@ namespace osu.Game.Rulesets.Osu.Utils
/// <returns>The rotated vector.</returns> /// <returns>The rotated vector.</returns>
public static Vector2 RotateVectorTowardsVector(Vector2 initial, Vector2 destination, float rotationRatio) public static Vector2 RotateVectorTowardsVector(Vector2 initial, Vector2 destination, float rotationRatio)
{ {
var initialAngleRad = MathF.Atan2(initial.Y, initial.X); float initialAngleRad = MathF.Atan2(initial.Y, initial.X);
var destAngleRad = MathF.Atan2(destination.Y, destination.X); float destAngleRad = MathF.Atan2(destination.Y, destination.X);
var diff = destAngleRad - initialAngleRad; float diff = destAngleRad - initialAngleRad;
while (diff < -MathF.PI) diff += 2 * MathF.PI; while (diff < -MathF.PI) diff += 2 * MathF.PI;
while (diff > MathF.PI) diff -= 2 * MathF.PI; while (diff > MathF.PI) diff -= 2 * MathF.PI;
var finalAngleRad = initialAngleRad + rotationRatio * diff; float finalAngleRad = initialAngleRad + rotationRatio * diff;
return new Vector2( return new Vector2(
initial.Length * MathF.Cos(finalAngleRad), initial.Length * MathF.Cos(finalAngleRad),

View File

@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Taiko.Tests
{ {
base.SetUpSteps(); base.SetUpSteps();
var expectedSampleNames = new[] string[] expectedSampleNames =
{ {
string.Empty, string.Empty,
string.Empty, string.Empty,
@ -31,6 +31,7 @@ namespace osu.Game.Rulesets.Taiko.Tests
HitSampleInfo.HIT_WHISTLE, HitSampleInfo.HIT_WHISTLE,
HitSampleInfo.HIT_WHISTLE, HitSampleInfo.HIT_WHISTLE,
}; };
var actualSampleNames = new List<string>(); var actualSampleNames = new List<string>();
// due to pooling we can't access all samples right away due to object re-use, // due to pooling we can't access all samples right away due to object re-use,

View File

@ -79,7 +79,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps
{ {
case IHasDistance distanceData: case IHasDistance distanceData:
{ {
if (shouldConvertSliderToHits(obj, beatmap, distanceData, out var taikoDuration, out var tickSpacing)) if (shouldConvertSliderToHits(obj, beatmap, distanceData, out int taikoDuration, out double tickSpacing))
{ {
List<IList<HitSampleInfo>> allSamples = obj is IHasPathWithRepeats curveData ? curveData.NodeSamples : new List<IList<HitSampleInfo>>(new[] { samples }); List<IList<HitSampleInfo>> allSamples = obj is IHasPathWithRepeats curveData ? curveData.NodeSamples : new List<IList<HitSampleInfo>>(new[] { samples });

View File

@ -109,7 +109,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
var corrected = samples.ToList(); var corrected = samples.ToList();
for (var i = 0; i < corrected.Count; i++) for (int i = 0; i < corrected.Count; i++)
{ {
var s = corrected[i]; var s = corrected[i];
@ -156,7 +156,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
validActionPressed = HitActions.Contains(e.Action); validActionPressed = HitActions.Contains(e.Action);
// Only count this as handled if the new judgement is a hit // Only count this as handled if the new judgement is a hit
var result = UpdateResult(true); bool result = UpdateResult(true);
if (IsHit) if (IsHit)
HitAction = e.Action; HitAction = e.Action;

View File

@ -185,9 +185,9 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
nextTick?.TriggerResult(true); nextTick?.TriggerResult(true);
var numHits = ticks.Count(r => r.IsHit); int numHits = ticks.Count(r => r.IsHit);
var completion = (float)numHits / HitObject.RequiredHits; float completion = (float)numHits / HitObject.RequiredHits;
expandingRing expandingRing
.FadeTo(expandingRing.Alpha + Math.Clamp(completion / 16, 0.1f, 0.6f), 50) .FadeTo(expandingRing.Alpha + Math.Clamp(completion / 16, 0.1f, 0.6f), 50)
@ -273,7 +273,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
if (Time.Current < HitObject.StartTime) if (Time.Current < HitObject.StartTime)
return false; return false;
var isCentre = e.Action == TaikoAction.LeftCentre || e.Action == TaikoAction.RightCentre; bool isCentre = e.Action == TaikoAction.LeftCentre || e.Action == TaikoAction.RightCentre;
// Ensure alternating centre and rim hits // Ensure alternating centre and rim hits
if (lastWasCentre == isCentre) if (lastWasCentre == isCentre)

View File

@ -69,7 +69,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
// because the right half is flipped, we need to position using width - position to get the true "topleft" origin position // because the right half is flipped, we need to position using width - position to get the true "topleft" origin position
float negativeScaleAdjust = content.Width / ratio; float negativeScaleAdjust = content.Width / ratio;
if (skin.GetConfig<LegacySkinConfiguration.LegacySetting, decimal>(LegacySkinConfiguration.LegacySetting.Version)?.Value >= 2.1m) if (skin.GetConfig<SkinConfiguration.LegacySetting, decimal>(SkinConfiguration.LegacySetting.Version)?.Value >= 2.1m)
{ {
left.Centre.Position = new Vector2(0, taiko_bar_y) * ratio; left.Centre.Position = new Vector2(0, taiko_bar_y) * ratio;
right.Centre.Position = new Vector2(negativeScaleAdjust - 56, taiko_bar_y) * ratio; right.Centre.Position = new Vector2(negativeScaleAdjust - 56, taiko_bar_y) * ratio;

View File

@ -91,7 +91,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
case TaikoSkinComponents.TaikoExplosionOk: case TaikoSkinComponents.TaikoExplosionOk:
case TaikoSkinComponents.TaikoExplosionGreat: case TaikoSkinComponents.TaikoExplosionGreat:
var hitName = getHitName(taikoComponent.Component); string hitName = getHitName(taikoComponent.Component);
var hitSprite = this.GetAnimation(hitName, true, false); var hitSprite = this.GetAnimation(hitName, true, false);
if (hitSprite != null) if (hitSprite != null)
@ -162,10 +162,10 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
{ {
get get
{ {
foreach (var name in base.LookupNames) foreach (string name in base.LookupNames)
yield return name.Insert(name.LastIndexOf('/') + 1, "taiko-"); yield return name.Insert(name.LastIndexOf('/') + 1, "taiko-");
foreach (var name in base.LookupNames) foreach (string name in base.LookupNames)
yield return name; yield return name;
} }
} }

View File

@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Taiko.UI
base.Update(); base.Update();
// Remove any auxiliary hit notes that were spawned during a drum roll but subsequently rewound. // Remove any auxiliary hit notes that were spawned during a drum roll but subsequently rewound.
for (var i = AliveInternalChildren.Count - 1; i >= 0; i--) for (int i = AliveInternalChildren.Count - 1; i >= 0; i--)
{ {
var flyingHit = (DrawableFlyingHit)AliveInternalChildren[i]; var flyingHit = (DrawableFlyingHit)AliveInternalChildren[i];
if (Time.Current <= flyingHit.HitObject.StartTime) if (Time.Current <= flyingHit.HitObject.StartTime)

View File

@ -122,7 +122,7 @@ namespace osu.Game.Rulesets.Taiko.UI
if (skin == null) return; if (skin == null) return;
foreach (var frameIndex in clear_animation_sequence) foreach (int frameIndex in clear_animation_sequence)
{ {
var texture = getAnimationFrame(skin, TaikoMascotAnimationState.Clear, frameIndex); var texture = getAnimationFrame(skin, TaikoMascotAnimationState.Clear, frameIndex);

View File

@ -40,7 +40,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
protected override bool ShouldSkipLine(string line) protected override bool ShouldSkipLine(string line)
{ {
var result = base.ShouldSkipLine(line); bool result = base.ShouldSkipLine(line);
if (!result) if (!result)
ParsedLines.Add(line); ParsedLines.Add(line);

View File

@ -82,7 +82,7 @@ namespace osu.Game.Tests.Beatmaps.IO
{ {
var osu = LoadOsuIntoHost(host); var osu = LoadOsuIntoHost(host);
var tempPath = TestResources.GetTestBeatmapForImport(); string tempPath = TestResources.GetTestBeatmapForImport();
var manager = osu.Dependencies.Get<BeatmapManager>(); var manager = osu.Dependencies.Get<BeatmapManager>();
@ -144,7 +144,7 @@ namespace osu.Game.Tests.Beatmaps.IO
{ {
var osu = LoadOsuIntoHost(host); var osu = LoadOsuIntoHost(host);
var temp = TestResources.GetTestBeatmapForImport(); string temp = TestResources.GetTestBeatmapForImport();
string extractedFolder = $"{temp}_extracted"; string extractedFolder = $"{temp}_extracted";
Directory.CreateDirectory(extractedFolder); Directory.CreateDirectory(extractedFolder);
@ -196,7 +196,7 @@ namespace osu.Game.Tests.Beatmaps.IO
{ {
var osu = LoadOsuIntoHost(host); var osu = LoadOsuIntoHost(host);
var temp = TestResources.GetTestBeatmapForImport(); string temp = TestResources.GetTestBeatmapForImport();
string extractedFolder = $"{temp}_extracted"; string extractedFolder = $"{temp}_extracted";
Directory.CreateDirectory(extractedFolder); Directory.CreateDirectory(extractedFolder);
@ -251,7 +251,7 @@ namespace osu.Game.Tests.Beatmaps.IO
{ {
var osu = LoadOsuIntoHost(host); var osu = LoadOsuIntoHost(host);
var temp = TestResources.GetTestBeatmapForImport(); string temp = TestResources.GetTestBeatmapForImport();
string extractedFolder = $"{temp}_extracted"; string extractedFolder = $"{temp}_extracted";
Directory.CreateDirectory(extractedFolder); Directory.CreateDirectory(extractedFolder);
@ -302,7 +302,7 @@ namespace osu.Game.Tests.Beatmaps.IO
{ {
var osu = LoadOsuIntoHost(host); var osu = LoadOsuIntoHost(host);
var temp = TestResources.GetTestBeatmapForImport(); string temp = TestResources.GetTestBeatmapForImport();
string extractedFolder = $"{temp}_extracted"; string extractedFolder = $"{temp}_extracted";
Directory.CreateDirectory(extractedFolder); Directory.CreateDirectory(extractedFolder);
@ -424,7 +424,7 @@ namespace osu.Game.Tests.Beatmaps.IO
checkBeatmapCount(osu, 12); checkBeatmapCount(osu, 12);
checkSingleReferencedFileCount(osu, 18); checkSingleReferencedFileCount(osu, 18);
var brokenTempFilename = TestResources.GetTestBeatmapForImport(); string brokenTempFilename = TestResources.GetTestBeatmapForImport();
MemoryStream brokenOsu = new MemoryStream(); MemoryStream brokenOsu = new MemoryStream();
MemoryStream brokenOsz = new MemoryStream(await File.ReadAllBytesAsync(brokenTempFilename)); MemoryStream brokenOsz = new MemoryStream(await File.ReadAllBytesAsync(brokenTempFilename));
@ -594,7 +594,7 @@ namespace osu.Game.Tests.Beatmaps.IO
var osu = LoadOsuIntoHost(host); var osu = LoadOsuIntoHost(host);
var temp = TestResources.GetTestBeatmapForImport(); string temp = TestResources.GetTestBeatmapForImport();
var importer = new ArchiveImportIPCChannel(client); var importer = new ArchiveImportIPCChannel(client);
if (!importer.ImportAsync(temp).Wait(10000)) if (!importer.ImportAsync(temp).Wait(10000))
@ -619,7 +619,7 @@ namespace osu.Game.Tests.Beatmaps.IO
try try
{ {
var osu = LoadOsuIntoHost(host); var osu = LoadOsuIntoHost(host);
var temp = TestResources.GetTestBeatmapForImport(); string temp = TestResources.GetTestBeatmapForImport();
using (File.OpenRead(temp)) using (File.OpenRead(temp))
await osu.Dependencies.Get<BeatmapManager>().Import(temp); await osu.Dependencies.Get<BeatmapManager>().Import(temp);
ensureLoaded(osu); ensureLoaded(osu);
@ -642,7 +642,7 @@ namespace osu.Game.Tests.Beatmaps.IO
{ {
var osu = LoadOsuIntoHost(host); var osu = LoadOsuIntoHost(host);
var temp = TestResources.GetTestBeatmapForImport(); string temp = TestResources.GetTestBeatmapForImport();
string extractedFolder = $"{temp}_extracted"; string extractedFolder = $"{temp}_extracted";
Directory.CreateDirectory(extractedFolder); Directory.CreateDirectory(extractedFolder);
@ -684,7 +684,7 @@ namespace osu.Game.Tests.Beatmaps.IO
{ {
var osu = LoadOsuIntoHost(host); var osu = LoadOsuIntoHost(host);
var temp = TestResources.GetTestBeatmapForImport(); string temp = TestResources.GetTestBeatmapForImport();
string extractedFolder = $"{temp}_extracted"; string extractedFolder = $"{temp}_extracted";
string subfolder = Path.Combine(extractedFolder, "subfolder"); string subfolder = Path.Combine(extractedFolder, "subfolder");
@ -729,7 +729,7 @@ namespace osu.Game.Tests.Beatmaps.IO
{ {
var osu = LoadOsuIntoHost(host); var osu = LoadOsuIntoHost(host);
var temp = TestResources.GetTestBeatmapForImport(); string temp = TestResources.GetTestBeatmapForImport();
string extractedFolder = $"{temp}_extracted"; string extractedFolder = $"{temp}_extracted";
string dataFolder = Path.Combine(extractedFolder, "actual_data"); string dataFolder = Path.Combine(extractedFolder, "actual_data");
@ -784,7 +784,7 @@ namespace osu.Game.Tests.Beatmaps.IO
var osu = LoadOsuIntoHost(host); var osu = LoadOsuIntoHost(host);
var manager = osu.Dependencies.Get<BeatmapManager>(); var manager = osu.Dependencies.Get<BeatmapManager>();
var temp = TestResources.GetTestBeatmapForImport(); string temp = TestResources.GetTestBeatmapForImport();
await osu.Dependencies.Get<BeatmapManager>().Import(temp); await osu.Dependencies.Get<BeatmapManager>().Import(temp);
// Update via the beatmap, not the beatmap info, to ensure correct linking // Update via the beatmap, not the beatmap info, to ensure correct linking
@ -814,7 +814,7 @@ namespace osu.Game.Tests.Beatmaps.IO
var osu = LoadOsuIntoHost(host); var osu = LoadOsuIntoHost(host);
var manager = osu.Dependencies.Get<BeatmapManager>(); var manager = osu.Dependencies.Get<BeatmapManager>();
var temp = TestResources.GetTestBeatmapForImport(); string temp = TestResources.GetTestBeatmapForImport();
await osu.Dependencies.Get<BeatmapManager>().Import(temp); await osu.Dependencies.Get<BeatmapManager>().Import(temp);
BeatmapSetInfo setToUpdate = manager.GetAllUsableBeatmapSets()[0]; BeatmapSetInfo setToUpdate = manager.GetAllUsableBeatmapSets()[0];
@ -905,7 +905,7 @@ namespace osu.Game.Tests.Beatmaps.IO
public static async Task<BeatmapSetInfo> LoadQuickOszIntoOsu(OsuGameBase osu) public static async Task<BeatmapSetInfo> LoadQuickOszIntoOsu(OsuGameBase osu)
{ {
var temp = TestResources.GetQuickTestBeatmapForImport(); string temp = TestResources.GetQuickTestBeatmapForImport();
var manager = osu.Dependencies.Get<BeatmapManager>(); var manager = osu.Dependencies.Get<BeatmapManager>();
@ -920,7 +920,7 @@ namespace osu.Game.Tests.Beatmaps.IO
public static async Task<BeatmapSetInfo> LoadOszIntoOsu(OsuGameBase osu, string path = null, bool virtualTrack = false) public static async Task<BeatmapSetInfo> LoadOszIntoOsu(OsuGameBase osu, string path = null, bool virtualTrack = false)
{ {
var temp = path ?? TestResources.GetTestBeatmapForImport(virtualTrack); string temp = path ?? TestResources.GetTestBeatmapForImport(virtualTrack);
var manager = osu.Dependencies.Get<BeatmapManager>(); var manager = osu.Dependencies.Get<BeatmapManager>();

View File

@ -114,7 +114,7 @@ namespace osu.Game.Tests.Beatmaps.IO
Assert.AreEqual("this line is gone", bufferedReader.ReadLine()); Assert.AreEqual("this line is gone", bufferedReader.ReadLine());
Assert.AreEqual("this one shouldn't be", bufferedReader.PeekLine()); Assert.AreEqual("this one shouldn't be", bufferedReader.PeekLine());
var endingLines = bufferedReader.ReadToEnd().Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); string[] endingLines = bufferedReader.ReadToEnd().Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
Assert.AreEqual(3, endingLines.Length); Assert.AreEqual(3, endingLines.Length);
Assert.AreEqual("this one shouldn't be", endingLines[0]); Assert.AreEqual("this one shouldn't be", endingLines[0]);
Assert.AreEqual("these ones", endingLines[1]); Assert.AreEqual("these ones", endingLines[1]);

View File

@ -36,8 +36,8 @@ namespace osu.Game.Tests.Beatmaps.IO
"Soleily - Renatus (MMzz) [Muzukashii].osu", "Soleily - Renatus (MMzz) [Muzukashii].osu",
"Soleily - Renatus (MMzz) [Oni].osu" "Soleily - Renatus (MMzz) [Oni].osu"
}; };
var maps = reader.Filenames.ToArray(); string[] maps = reader.Filenames.ToArray();
foreach (var map in expected) foreach (string map in expected)
Assert.Contains(map, maps); Assert.Contains(map, maps);
} }
} }

View File

@ -94,7 +94,7 @@ namespace osu.Game.Tests.Database
using var importer = new BeatmapImporter(realmFactory, storage); using var importer = new BeatmapImporter(realmFactory, storage);
using var store = new RealmRulesetStore(realmFactory, storage); using var store = new RealmRulesetStore(realmFactory, storage);
var tempPath = TestResources.GetTestBeatmapForImport(); string? tempPath = TestResources.GetTestBeatmapForImport();
ILive<RealmBeatmapSet>? importedSet; ILive<RealmBeatmapSet>? importedSet;
@ -144,7 +144,7 @@ namespace osu.Game.Tests.Database
using var importer = new BeatmapImporter(realmFactory, storage); using var importer = new BeatmapImporter(realmFactory, storage);
using var store = new RealmRulesetStore(realmFactory, storage); using var store = new RealmRulesetStore(realmFactory, storage);
var temp = TestResources.GetTestBeatmapForImport(); string? temp = TestResources.GetTestBeatmapForImport();
string extractedFolder = $"{temp}_extracted"; string extractedFolder = $"{temp}_extracted";
Directory.CreateDirectory(extractedFolder); Directory.CreateDirectory(extractedFolder);
@ -193,7 +193,7 @@ namespace osu.Game.Tests.Database
using var importer = new BeatmapImporter(realmFactory, storage); using var importer = new BeatmapImporter(realmFactory, storage);
using var store = new RealmRulesetStore(realmFactory, storage); using var store = new RealmRulesetStore(realmFactory, storage);
var temp = TestResources.GetTestBeatmapForImport(); string? temp = TestResources.GetTestBeatmapForImport();
string extractedFolder = $"{temp}_extracted"; string extractedFolder = $"{temp}_extracted";
Directory.CreateDirectory(extractedFolder); Directory.CreateDirectory(extractedFolder);
@ -245,7 +245,7 @@ namespace osu.Game.Tests.Database
using var importer = new BeatmapImporter(realmFactory, storage); using var importer = new BeatmapImporter(realmFactory, storage);
using var store = new RealmRulesetStore(realmFactory, storage); using var store = new RealmRulesetStore(realmFactory, storage);
var temp = TestResources.GetTestBeatmapForImport(); string? temp = TestResources.GetTestBeatmapForImport();
string extractedFolder = $"{temp}_extracted"; string extractedFolder = $"{temp}_extracted";
Directory.CreateDirectory(extractedFolder); Directory.CreateDirectory(extractedFolder);
@ -293,7 +293,7 @@ namespace osu.Game.Tests.Database
using var importer = new BeatmapImporter(realmFactory, storage); using var importer = new BeatmapImporter(realmFactory, storage);
using var store = new RealmRulesetStore(realmFactory, storage); using var store = new RealmRulesetStore(realmFactory, storage);
var temp = TestResources.GetTestBeatmapForImport(); string? temp = TestResources.GetTestBeatmapForImport();
string extractedFolder = $"{temp}_extracted"; string extractedFolder = $"{temp}_extracted";
Directory.CreateDirectory(extractedFolder); Directory.CreateDirectory(extractedFolder);
@ -391,7 +391,7 @@ namespace osu.Game.Tests.Database
checkBeatmapCount(realmFactory.Context, 12); checkBeatmapCount(realmFactory.Context, 12);
checkSingleReferencedFileCount(realmFactory.Context, 18); checkSingleReferencedFileCount(realmFactory.Context, 18);
var brokenTempFilename = TestResources.GetTestBeatmapForImport(); string? brokenTempFilename = TestResources.GetTestBeatmapForImport();
MemoryStream brokenOsu = new MemoryStream(); MemoryStream brokenOsu = new MemoryStream();
MemoryStream brokenOsz = new MemoryStream(await File.ReadAllBytesAsync(brokenTempFilename)); MemoryStream brokenOsz = new MemoryStream(await File.ReadAllBytesAsync(brokenTempFilename));
@ -522,7 +522,7 @@ namespace osu.Game.Tests.Database
using var importer = new BeatmapImporter(realmFactory, storage); using var importer = new BeatmapImporter(realmFactory, storage);
using var store = new RealmRulesetStore(realmFactory, storage); using var store = new RealmRulesetStore(realmFactory, storage);
var temp = TestResources.GetTestBeatmapForImport(); string? temp = TestResources.GetTestBeatmapForImport();
using (File.OpenRead(temp)) using (File.OpenRead(temp))
await importer.Import(temp); await importer.Import(temp);
ensureLoaded(realmFactory.Context); ensureLoaded(realmFactory.Context);
@ -539,7 +539,7 @@ namespace osu.Game.Tests.Database
using var importer = new BeatmapImporter(realmFactory, storage); using var importer = new BeatmapImporter(realmFactory, storage);
using var store = new RealmRulesetStore(realmFactory, storage); using var store = new RealmRulesetStore(realmFactory, storage);
var temp = TestResources.GetTestBeatmapForImport(); string? temp = TestResources.GetTestBeatmapForImport();
string extractedFolder = $"{temp}_extracted"; string extractedFolder = $"{temp}_extracted";
Directory.CreateDirectory(extractedFolder); Directory.CreateDirectory(extractedFolder);
@ -575,7 +575,7 @@ namespace osu.Game.Tests.Database
using var importer = new BeatmapImporter(realmFactory, storage); using var importer = new BeatmapImporter(realmFactory, storage);
using var store = new RealmRulesetStore(realmFactory, storage); using var store = new RealmRulesetStore(realmFactory, storage);
var temp = TestResources.GetTestBeatmapForImport(); string? temp = TestResources.GetTestBeatmapForImport();
string extractedFolder = $"{temp}_extracted"; string extractedFolder = $"{temp}_extracted";
string subfolder = Path.Combine(extractedFolder, "subfolder"); string subfolder = Path.Combine(extractedFolder, "subfolder");
@ -617,7 +617,7 @@ namespace osu.Game.Tests.Database
using var importer = new BeatmapImporter(realmFactory, storage); using var importer = new BeatmapImporter(realmFactory, storage);
using var store = new RealmRulesetStore(realmFactory, storage); using var store = new RealmRulesetStore(realmFactory, storage);
var temp = TestResources.GetTestBeatmapForImport(); string? temp = TestResources.GetTestBeatmapForImport();
string extractedFolder = $"{temp}_extracted"; string extractedFolder = $"{temp}_extracted";
string dataFolder = Path.Combine(extractedFolder, "actual_data"); string dataFolder = Path.Combine(extractedFolder, "actual_data");
@ -668,7 +668,7 @@ namespace osu.Game.Tests.Database
using var importer = new BeatmapImporter(realmFactory, storage); using var importer = new BeatmapImporter(realmFactory, storage);
using var store = new RealmRulesetStore(realmFactory, storage); using var store = new RealmRulesetStore(realmFactory, storage);
var temp = TestResources.GetTestBeatmapForImport(); string? temp = TestResources.GetTestBeatmapForImport();
await importer.Import(temp); await importer.Import(temp);
// Update via the beatmap, not the beatmap info, to ensure correct linking // Update via the beatmap, not the beatmap info, to ensure correct linking
@ -685,7 +685,7 @@ namespace osu.Game.Tests.Database
public static async Task<RealmBeatmapSet?> LoadQuickOszIntoOsu(BeatmapImporter importer, Realm realm) public static async Task<RealmBeatmapSet?> LoadQuickOszIntoOsu(BeatmapImporter importer, Realm realm)
{ {
var temp = TestResources.GetQuickTestBeatmapForImport(); string? temp = TestResources.GetQuickTestBeatmapForImport();
var importedSet = await importer.Import(new ImportTask(temp)); var importedSet = await importer.Import(new ImportTask(temp));
@ -700,7 +700,7 @@ namespace osu.Game.Tests.Database
public static async Task<RealmBeatmapSet> LoadOszIntoStore(BeatmapImporter importer, Realm realm, string? path = null, bool virtualTrack = false) public static async Task<RealmBeatmapSet> LoadOszIntoStore(BeatmapImporter importer, Realm realm, string? path = null, bool virtualTrack = false)
{ {
var temp = path ?? TestResources.GetTestBeatmapForImport(virtualTrack); string? temp = path ?? TestResources.GetTestBeatmapForImport(virtualTrack);
var importedSet = await importer.Import(new ImportTask(temp)); var importedSet = await importer.Import(new ImportTask(temp));

View File

@ -7,7 +7,7 @@ using osu.Game.Rulesets;
using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu;
using osu.Game.Tests.Beatmaps; using osu.Game.Tests.Beatmaps;
using osu.Game.Tests.Resources; using osu.Game.Tests.Resources;
using static osu.Game.Skinning.LegacySkinConfiguration; using static osu.Game.Skinning.SkinConfiguration;
namespace osu.Game.Tests.Gameplay namespace osu.Game.Tests.Gameplay
{ {

View File

@ -49,7 +49,7 @@ namespace osu.Game.Tests.NonVisual
for (int i = 0; i * beat_length_denominator < barLines.Count; i++) for (int i = 0; i * beat_length_denominator < barLines.Count; i++)
{ {
var barLine = barLines[i * beat_length_denominator]; var barLine = barLines[i * beat_length_denominator];
var expectedTime = beat_length_numerator * (int)signature * i; int expectedTime = beat_length_numerator * (int)signature * i;
// every seventh bar's start time should be at least greater than the whole number we expect. // every seventh bar's start time should be at least greater than the whole number we expect.
// It cannot be less, as that can affect overlapping scroll algorithms // It cannot be less, as that can affect overlapping scroll algorithms

View File

@ -87,7 +87,7 @@ namespace osu.Game.Tests.NonVisual
File.WriteAllText(actualTestFile, "test"); File.WriteAllText(actualTestFile, "test");
var rulesetStorage = storage.GetStorageForDirectory("rulesets"); var rulesetStorage = storage.GetStorageForDirectory("rulesets");
var lookupPath = rulesetStorage.GetFiles(".").Single(); string lookupPath = rulesetStorage.GetFiles(".").Single();
Assert.That(lookupPath, Is.EqualTo("test")); Assert.That(lookupPath, Is.EqualTo("test"));
} }
@ -140,7 +140,7 @@ namespace osu.Game.Tests.NonVisual
Assert.That(osuStorage, Is.Not.Null); Assert.That(osuStorage, Is.Not.Null);
foreach (var file in osuStorage.IgnoreFiles) foreach (string file in osuStorage.IgnoreFiles)
{ {
// avoid touching realm files which may be a pipe and break everything. // avoid touching realm files which may be a pipe and break everything.
// this is also done locally inside OsuStorage via the IgnoreFiles list. // this is also done locally inside OsuStorage via the IgnoreFiles list.
@ -149,7 +149,7 @@ namespace osu.Game.Tests.NonVisual
Assert.That(storage.Exists(file), Is.False); Assert.That(storage.Exists(file), Is.False);
} }
foreach (var dir in osuStorage.IgnoreDirectories) foreach (string dir in osuStorage.IgnoreDirectories)
{ {
Assert.That(Directory.Exists(Path.Combine(originalDirectory, dir))); Assert.That(Directory.Exists(Path.Combine(originalDirectory, dir)));
Assert.That(storage.ExistsDirectory(dir), Is.False); Assert.That(storage.ExistsDirectory(dir), Is.False);

View File

@ -347,7 +347,7 @@ namespace osu.Game.Tests.NonVisual
{ {
for (int i = 0; i < 1000; i++) for (int i = 0; i < 1000; i++)
{ {
var time = handler.SetFrameFromTime(destination); double? time = handler.SetFrameFromTime(destination);
if (time == null || time == destination) if (time == null || time == destination)
return; return;
} }

View File

@ -30,7 +30,7 @@ namespace osu.Game.Tests.NonVisual
Assert.Throws<InvalidOperationException>(() => _ = queue.Dequeue()); Assert.Throws<InvalidOperationException>(() => _ = queue.Dequeue());
int count = 0; int count = 0;
foreach (var _ in queue) foreach (int _ in queue)
count++; count++;
Assert.AreEqual(0, count); Assert.AreEqual(0, count);
@ -50,7 +50,7 @@ namespace osu.Game.Tests.NonVisual
Assert.AreEqual(i, queue[i]); Assert.AreEqual(i, queue[i]);
int j = 0; int j = 0;
foreach (var item in queue) foreach (int item in queue)
Assert.AreEqual(j++, item); Assert.AreEqual(j++, item);
for (int i = queue.Count; i < queue.Count + capacity; i++) for (int i = queue.Count; i < queue.Count + capacity; i++)
@ -71,7 +71,7 @@ namespace osu.Game.Tests.NonVisual
Assert.AreEqual(count - capacity + i, queue[i]); Assert.AreEqual(count - capacity + i, queue[i]);
int j = count - capacity; int j = count - capacity;
foreach (var item in queue) foreach (int item in queue)
Assert.AreEqual(j++, item); Assert.AreEqual(j++, item);
for (int i = queue.Count; i < queue.Count + capacity; i++) for (int i = queue.Count; i < queue.Count + capacity; i++)

View File

@ -84,7 +84,7 @@ namespace osu.Game.Tests.NonVisual.Multiplayer
{ {
for (int i = 0; i < userCount; ++i) for (int i = 0; i < userCount; ++i)
{ {
var userId = Client.Room?.Users[i].UserID ?? throw new AssertionException("Room cannot be null!"); int userId = Client.Room?.Users[i].UserID ?? throw new AssertionException("Room cannot be null!");
Client.ChangeUserState(userId, state); Client.ChangeUserState(userId, state);
} }
}); });

View File

@ -29,7 +29,7 @@ namespace osu.Game.Tests.NonVisual
}); });
int count = 0; int count = 0;
foreach (var unused in queue) foreach (char unused in queue)
count++; count++;
Assert.AreEqual(0, count); Assert.AreEqual(0, count);
@ -72,7 +72,7 @@ namespace osu.Game.Tests.NonVisual
// Assert correct item return and no longer in queue after dequeueing // Assert correct item return and no longer in queue after dequeueing
Assert.AreEqual('a', queue[5]); Assert.AreEqual('a', queue[5]);
var dequeuedItem = queue.Dequeue(); char dequeuedItem = queue.Dequeue();
Assert.AreEqual('a', dequeuedItem); Assert.AreEqual('a', dequeuedItem);
Assert.AreEqual(5, queue.Count); Assert.AreEqual(5, queue.Count);
@ -133,7 +133,7 @@ namespace osu.Game.Tests.NonVisual
int expectedValueIndex = 0; int expectedValueIndex = 0;
// Assert items are enumerated in correct order // Assert items are enumerated in correct order
foreach (var item in queue) foreach (char item in queue)
{ {
Assert.AreEqual(expectedValues[expectedValueIndex], item); Assert.AreEqual(expectedValues[expectedValueIndex], item);
expectedValueIndex++; expectedValueIndex++;

View File

@ -20,7 +20,7 @@ namespace osu.Game.Tests.Online
MatchState = new TeamVersusRoomState() MatchState = new TeamVersusRoomState()
}; };
var serialized = MessagePackSerializer.Serialize(room); byte[] serialized = MessagePackSerializer.Serialize(room);
var deserialized = MessagePackSerializer.Deserialize<MultiplayerRoom>(serialized); var deserialized = MessagePackSerializer.Deserialize<MultiplayerRoom>(serialized);
@ -32,7 +32,7 @@ namespace osu.Game.Tests.Online
{ {
var state = new TeamVersusUserState(); var state = new TeamVersusUserState();
var serialized = MessagePackSerializer.Serialize(typeof(MatchUserState), state); byte[] serialized = MessagePackSerializer.Serialize(typeof(MatchUserState), state);
var deserialized = MessagePackSerializer.Deserialize<MatchUserState>(serialized); var deserialized = MessagePackSerializer.Deserialize<MatchUserState>(serialized);
Assert.IsTrue(deserialized is TeamVersusUserState); Assert.IsTrue(deserialized is TeamVersusUserState);
@ -44,7 +44,7 @@ namespace osu.Game.Tests.Online
var state = new TeamVersusUserState(); var state = new TeamVersusUserState();
// SignalR serialises using the actual type, rather than a base specification. // SignalR serialises using the actual type, rather than a base specification.
var serialized = MessagePackSerializer.Serialize(typeof(TeamVersusUserState), state); byte[] serialized = MessagePackSerializer.Serialize(typeof(TeamVersusUserState), state);
// works with explicit type specified. // works with explicit type specified.
MessagePackSerializer.Deserialize<TeamVersusUserState>(serialized); MessagePackSerializer.Deserialize<TeamVersusUserState>(serialized);
@ -59,7 +59,7 @@ namespace osu.Game.Tests.Online
var state = new TeamVersusUserState(); var state = new TeamVersusUserState();
// SignalR serialises using the actual type, rather than a base specification. // SignalR serialises using the actual type, rather than a base specification.
var serialized = MessagePackSerializer.Serialize(typeof(TeamVersusUserState), state, SignalRUnionWorkaroundResolver.OPTIONS); byte[] serialized = MessagePackSerializer.Serialize(typeof(TeamVersusUserState), state, SignalRUnionWorkaroundResolver.OPTIONS);
// works with explicit type specified. // works with explicit type specified.
MessagePackSerializer.Deserialize<TeamVersusUserState>(serialized); MessagePackSerializer.Deserialize<TeamVersusUserState>(serialized);

View File

@ -29,7 +29,7 @@ namespace osu.Game.Tests.Resources
/// <returns>A path to a copy of a beatmap archive (osz). Should be deleted after use.</returns> /// <returns>A path to a copy of a beatmap archive (osz). Should be deleted after use.</returns>
public static string GetQuickTestBeatmapForImport() public static string GetQuickTestBeatmapForImport()
{ {
var tempPath = getTempFilename(); string tempPath = getTempFilename();
using (var stream = OpenResource("Archives/241526 Soleily - Renatus_virtual_quick.osz")) using (var stream = OpenResource("Archives/241526 Soleily - Renatus_virtual_quick.osz"))
using (var newFile = File.Create(tempPath)) using (var newFile = File.Create(tempPath))
stream.CopyTo(newFile); stream.CopyTo(newFile);
@ -45,7 +45,7 @@ namespace osu.Game.Tests.Resources
/// <returns>A path to a copy of a beatmap archive (osz). Should be deleted after use.</returns> /// <returns>A path to a copy of a beatmap archive (osz). Should be deleted after use.</returns>
public static string GetTestBeatmapForImport(bool virtualTrack = false) public static string GetTestBeatmapForImport(bool virtualTrack = false)
{ {
var tempPath = getTempFilename(); string tempPath = getTempFilename();
using (var stream = GetTestBeatmapStream(virtualTrack)) using (var stream = GetTestBeatmapStream(virtualTrack))
using (var newFile = File.Create(tempPath)) using (var newFile = File.Create(tempPath))

View File

@ -4,10 +4,12 @@
using System; using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading.Tasks; using System.Threading.Tasks;
using NUnit.Framework; using NUnit.Framework;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Platform; using osu.Framework.Platform;
using osu.Game.IO;
using osu.Game.IO.Archives; using osu.Game.IO.Archives;
using osu.Game.Skinning; using osu.Game.Skinning;
using SharpCompress.Archives.Zip; using SharpCompress.Archives.Zip;
@ -16,155 +18,179 @@ namespace osu.Game.Tests.Skins.IO
{ {
public class ImportSkinTest : ImportTest public class ImportSkinTest : ImportTest
{ {
[Test] #region Testing filename metadata inclusion
public async Task TestBasicImport()
{
using (HeadlessGameHost host = new CleanRunHeadlessGameHost(nameof(ImportSkinTest)))
{
try
{
var osu = LoadOsuIntoHost(host);
var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("test skin", "skinner"), "skin.osk"));
Assert.That(imported.Name, Is.EqualTo("test skin"));
Assert.That(imported.Creator, Is.EqualTo("skinner"));
}
finally
{
host.Exit();
}
}
}
[Test] [Test]
public async Task TestImportTwiceWithSameMetadata() public Task TestSingleImportDifferentFilename() => runSkinTest(async osu =>
{ {
using (HeadlessGameHost host = new CleanRunHeadlessGameHost(nameof(ImportSkinTest))) var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin", "skinner"), "skin.osk"));
{
try
{
var osu = LoadOsuIntoHost(host);
var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("test skin", "skinner"), "skin.osk")); // When the import filename doesn't match, it should be appended (and update the skin.ini).
var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("test skin", "skinner"), "skin2.osk")); assertCorrectMetadata(import1, "test skin [skin]", "skinner", osu);
});
Assert.That(imported2.ID, Is.Not.EqualTo(imported.ID));
Assert.That(osu.Dependencies.Get<SkinManager>().GetAllUserSkins(true).Count, Is.EqualTo(1));
// the first should be overwritten by the second import.
Assert.That(osu.Dependencies.Get<SkinManager>().GetAllUserSkins(true).First().Files.First().FileInfoID, Is.EqualTo(imported2.Files.First().FileInfoID));
}
finally
{
host.Exit();
}
}
}
[Test] [Test]
public async Task TestImportTwiceWithNoMetadata() public Task TestSingleImportMatchingFilename() => runSkinTest(async osu =>
{ {
using (HeadlessGameHost host = new CleanRunHeadlessGameHost(nameof(ImportSkinTest))) var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin", "skinner"), "test skin.osk"));
{
try
{
var osu = LoadOsuIntoHost(host);
// When the import filename matches it shouldn't be appended.
assertCorrectMetadata(import1, "test skin", "skinner", osu);
});
[Test]
public Task TestSingleImportNoIniFile() => runSkinTest(async osu =>
{
var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithNonIniFile(), "test skin.osk"));
// When the import filename matches it shouldn't be appended.
assertCorrectMetadata(import1, "test skin", "Unknown", osu);
});
[Test]
public Task TestEmptyImportImportsWithFilename() => runSkinTest(async osu =>
{
var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createEmptyOsk(), "test skin.osk"));
// When the import filename matches it shouldn't be appended.
assertCorrectMetadata(import1, "test skin", "Unknown", osu);
});
#endregion
#region Cases where imports should match existing
[Test]
public Task TestImportTwiceWithSameMetadataAndFilename() => runSkinTest(async osu =>
{
var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin", "skinner"), "skin.osk"));
var import2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin", "skinner"), "skin.osk"));
assertImportedOnce(import1, import2);
});
[Test]
public Task TestImportTwiceWithNoMetadataSameDownloadFilename() => runSkinTest(async osu =>
{
// if a user downloads two skins that do have skin.ini files but don't have any creator metadata in the skin.ini, they should both import separately just for safety. // if a user downloads two skins that do have skin.ini files but don't have any creator metadata in the skin.ini, they should both import separately just for safety.
var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk(string.Empty, string.Empty), "download.osk")); var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni(string.Empty, string.Empty), "download.osk"));
var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk(string.Empty, string.Empty), "download.osk")); var import2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni(string.Empty, string.Empty), "download.osk"));
Assert.That(imported2.ID, Is.Not.EqualTo(imported.ID)); assertImportedOnce(import1, import2);
Assert.That(osu.Dependencies.Get<SkinManager>().GetAllUserSkins(true).Count, Is.EqualTo(2)); });
Assert.That(osu.Dependencies.Get<SkinManager>().GetAllUserSkins(true).First().Files.First().FileInfoID, Is.EqualTo(imported.Files.First().FileInfoID));
Assert.That(osu.Dependencies.Get<SkinManager>().GetAllUserSkins(true).Last().Files.First().FileInfoID, Is.EqualTo(imported2.Files.First().FileInfoID));
}
finally
{
host.Exit();
}
}
}
[Test] [Test]
public async Task TestImportTwiceWithDifferentMetadata() public Task TestImportUpperCasedOskArchive() => runSkinTest(async osu =>
{ {
using (HeadlessGameHost host = new CleanRunHeadlessGameHost(nameof(ImportSkinTest))) var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("name 1", "author 1"), "name 1.OsK"));
{ assertCorrectMetadata(import1, "name 1", "author 1", osu);
try
{
var osu = LoadOsuIntoHost(host);
var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("test skin v2", "skinner"), "skin.osk")); var import2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("name 1", "author 1"), "name 1.oSK"));
var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("test skin v2.1", "skinner"), "skin2.osk"));
Assert.That(imported2.ID, Is.Not.EqualTo(imported.ID)); assertImportedOnce(import1, import2);
Assert.That(osu.Dependencies.Get<SkinManager>().GetAllUserSkins(true).Count, Is.EqualTo(2)); });
Assert.That(osu.Dependencies.Get<SkinManager>().GetAllUserSkins(true).First().Files.First().FileInfoID, Is.EqualTo(imported.Files.First().FileInfoID));
Assert.That(osu.Dependencies.Get<SkinManager>().GetAllUserSkins(true).Last().Files.First().FileInfoID, Is.EqualTo(imported2.Files.First().FileInfoID));
}
finally
{
host.Exit();
}
}
}
[Test] [Test]
public async Task TestImportUpperCasedOskArchive() public Task TestSameMetadataNameSameFolderName() => runSkinTest(async osu =>
{ {
using (HeadlessGameHost host = new CleanRunHeadlessGameHost(nameof(ImportSkinTest))) var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("name 1", "author 1"), "my custom skin 1"));
{ var import2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("name 1", "author 1"), "my custom skin 1"));
try
{
var osu = LoadOsuIntoHost(host);
var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("name 1", "author 1"), "skin1.OsK")); assertImportedOnce(import1, import2);
assertCorrectMetadata(import1, "name 1 [my custom skin 1]", "author 1", osu);
});
Assert.That(imported.Name, Is.EqualTo("name 1")); #endregion
Assert.That(imported.Creator, Is.EqualTo("author 1"));
var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("name 1", "author 1"), "skin1.oSK")); #region Cases where imports should be uniquely imported
Assert.That(imported2.Hash, Is.EqualTo(imported.Hash));
}
finally
{
host.Exit();
}
}
}
[Test] [Test]
public async Task TestSameMetadataNameDifferentFolderName() public Task TestImportTwiceWithSameMetadataButDifferentFilename() => runSkinTest(async osu =>
{ {
using (HeadlessGameHost host = new CleanRunHeadlessGameHost(nameof(ImportSkinTest))) var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin", "skinner"), "skin.osk"));
{ var import2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin", "skinner"), "skin2.osk"));
try
{
var osu = LoadOsuIntoHost(host);
var imported = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("name 1", "author 1", false), "my custom skin 1")); assertImportedBoth(import1, import2);
Assert.That(imported.Name, Is.EqualTo("name 1 [my custom skin 1]")); });
Assert.That(imported.Creator, Is.EqualTo("author 1"));
var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("name 1", "author 1", false), "my custom skin 2")); [Test]
Assert.That(imported2.Name, Is.EqualTo("name 1 [my custom skin 2]")); public Task TestImportTwiceWithNoMetadataDifferentDownloadFilename() => runSkinTest(async osu =>
Assert.That(imported2.Creator, Is.EqualTo("author 1"));
Assert.That(imported2.Hash, Is.Not.EqualTo(imported.Hash));
}
finally
{ {
host.Exit(); // if a user downloads two skins that do have skin.ini files but don't have any creator metadata in the skin.ini, they should both import separately just for safety.
} var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni(string.Empty, string.Empty), "download.osk"));
} var import2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni(string.Empty, string.Empty), "download2.osk"));
assertImportedBoth(import1, import2);
});
[Test]
public Task TestImportTwiceWithSameFilenameDifferentMetadata() => runSkinTest(async osu =>
{
var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin v2", "skinner"), "skin.osk"));
var import2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin v2.1", "skinner"), "skin.osk"));
assertImportedBoth(import1, import2);
assertCorrectMetadata(import1, "test skin v2 [skin]", "skinner", osu);
assertCorrectMetadata(import2, "test skin v2.1 [skin]", "skinner", osu);
});
[Test]
public Task TestSameMetadataNameDifferentFolderName() => runSkinTest(async osu =>
{
var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("name 1", "author 1"), "my custom skin 1"));
var import2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("name 1", "author 1"), "my custom skin 2"));
assertImportedBoth(import1, import2);
assertCorrectMetadata(import1, "name 1 [my custom skin 1]", "author 1", osu);
assertCorrectMetadata(import2, "name 1 [my custom skin 2]", "author 1", osu);
});
#endregion
private void assertCorrectMetadata(SkinInfo import1, string name, string creator, OsuGameBase osu)
{
Assert.That(import1.Name, Is.EqualTo(name));
Assert.That(import1.Creator, Is.EqualTo(creator));
// for extra safety let's reconstruct the skin, reading from the skin.ini.
var instance = import1.CreateInstance((IStorageResourceProvider)osu.Dependencies.Get(typeof(SkinManager)));
Assert.That(instance.Configuration.SkinInfo.Name, Is.EqualTo(name));
Assert.That(instance.Configuration.SkinInfo.Creator, Is.EqualTo(creator));
} }
private MemoryStream createOsk(string name, string author, bool makeUnique = true) private void assertImportedBoth(SkinInfo import1, SkinInfo import2)
{
Assert.That(import2.ID, Is.Not.EqualTo(import1.ID));
Assert.That(import2.Hash, Is.Not.EqualTo(import1.Hash));
Assert.That(import2.Files.Select(f => f.FileInfoID), Is.Not.EquivalentTo(import1.Files.Select(f => f.FileInfoID)));
}
private void assertImportedOnce(SkinInfo import1, SkinInfo import2)
{
Assert.That(import2.ID, Is.EqualTo(import1.ID));
Assert.That(import2.Hash, Is.EqualTo(import1.Hash));
Assert.That(import2.Files.Select(f => f.FileInfoID), Is.EquivalentTo(import1.Files.Select(f => f.FileInfoID)));
}
private MemoryStream createEmptyOsk()
{
var zipStream = new MemoryStream();
using var zip = ZipArchive.Create();
zip.SaveTo(zipStream);
return zipStream;
}
private MemoryStream createOskWithNonIniFile()
{
var zipStream = new MemoryStream();
using var zip = ZipArchive.Create();
zip.AddEntry("hitcircle.png", new MemoryStream(new byte[] { 0, 1, 2, 3 }));
zip.SaveTo(zipStream);
return zipStream;
}
private MemoryStream createOskWithIni(string name, string author, bool makeUnique = false)
{ {
var zipStream = new MemoryStream(); var zipStream = new MemoryStream();
using var zip = ZipArchive.Create(); using var zip = ZipArchive.Create();
@ -193,6 +219,22 @@ namespace osu.Game.Tests.Skins.IO
return stream; return stream;
} }
private async Task runSkinTest(Func<OsuGameBase, Task> action, [CallerMemberName] string callingMethodName = @"")
{
using (HeadlessGameHost host = new CleanRunHeadlessGameHost(callingMethodName))
{
try
{
var osu = LoadOsuIntoHost(host);
await action(osu);
}
finally
{
host.Exit();
}
}
}
private async Task<SkinInfo> loadSkinIntoOsu(OsuGameBase osu, ArchiveReader archive = null) private async Task<SkinInfo> loadSkinIntoOsu(OsuGameBase osu, ArchiveReader archive = null)
{ {
var skinManager = osu.Dependencies.Get<SkinManager>(); var skinManager = osu.Dependencies.Get<SkinManager>();

View File

@ -106,7 +106,7 @@ namespace osu.Game.Tests.Skins
var decoder = new LegacySkinDecoder(); var decoder = new LegacySkinDecoder();
using (var resStream = TestResources.OpenResource("skin-latest.ini")) using (var resStream = TestResources.OpenResource("skin-latest.ini"))
using (var stream = new LineBufferedReader(resStream)) using (var stream = new LineBufferedReader(resStream))
Assert.AreEqual(LegacySkinConfiguration.LATEST_VERSION, decoder.Decode(stream).LegacyVersion); Assert.AreEqual(SkinConfiguration.LATEST_VERSION, decoder.Decode(stream).LegacyVersion);
} }
[Test] [Test]

View File

@ -151,7 +151,7 @@ namespace osu.Game.Tests.Skins
{ {
AddStep("Set user skin version 2.3", () => userSource.Configuration.LegacyVersion = 2.3m); AddStep("Set user skin version 2.3", () => userSource.Configuration.LegacyVersion = 2.3m);
AddStep("Set beatmap skin version null", () => beatmapSource.Configuration.LegacyVersion = null); AddStep("Set beatmap skin version null", () => beatmapSource.Configuration.LegacyVersion = null);
AddAssert("Check legacy version lookup", () => requester.GetConfig<LegacySkinConfiguration.LegacySetting, decimal>(LegacySkinConfiguration.LegacySetting.Version)?.Value == 2.3m); AddAssert("Check legacy version lookup", () => requester.GetConfig<SkinConfiguration.LegacySetting, decimal>(SkinConfiguration.LegacySetting.Version)?.Value == 2.3m);
} }
[Test] [Test]
@ -160,7 +160,7 @@ namespace osu.Game.Tests.Skins
// completely ignoring beatmap versions for simplicity. // completely ignoring beatmap versions for simplicity.
AddStep("Set user skin version 2.3", () => userSource.Configuration.LegacyVersion = 2.3m); AddStep("Set user skin version 2.3", () => userSource.Configuration.LegacyVersion = 2.3m);
AddStep("Set beatmap skin version null", () => beatmapSource.Configuration.LegacyVersion = 1.7m); AddStep("Set beatmap skin version null", () => beatmapSource.Configuration.LegacyVersion = 1.7m);
AddAssert("Check legacy version lookup", () => requester.GetConfig<LegacySkinConfiguration.LegacySetting, decimal>(LegacySkinConfiguration.LegacySetting.Version)?.Value == 2.3m); AddAssert("Check legacy version lookup", () => requester.GetConfig<SkinConfiguration.LegacySetting, decimal>(SkinConfiguration.LegacySetting.Version)?.Value == 2.3m);
} }
[Test] [Test]
@ -169,14 +169,14 @@ namespace osu.Game.Tests.Skins
AddStep("Set user skin version 2.3", () => userSource.Configuration.LegacyVersion = null); AddStep("Set user skin version 2.3", () => userSource.Configuration.LegacyVersion = null);
AddStep("Set beatmap skin version null", () => beatmapSource.Configuration.LegacyVersion = null); AddStep("Set beatmap skin version null", () => beatmapSource.Configuration.LegacyVersion = null);
AddAssert("Check legacy version lookup", AddAssert("Check legacy version lookup",
() => requester.GetConfig<LegacySkinConfiguration.LegacySetting, decimal>(LegacySkinConfiguration.LegacySetting.Version)?.Value == LegacySkinConfiguration.LATEST_VERSION); () => requester.GetConfig<SkinConfiguration.LegacySetting, decimal>(SkinConfiguration.LegacySetting.Version)?.Value == SkinConfiguration.LATEST_VERSION);
} }
[Test] [Test]
public void TestIniWithNoVersionFallsBackTo1() public void TestIniWithNoVersionFallsBackTo1()
{ {
AddStep("Parse skin with no version", () => userSource.Configuration = new LegacySkinDecoder().Decode(new LineBufferedReader(new MemoryStream()))); AddStep("Parse skin with no version", () => userSource.Configuration = new LegacySkinDecoder().Decode(new LineBufferedReader(new MemoryStream())));
AddAssert("Check legacy version lookup", () => requester.GetConfig<LegacySkinConfiguration.LegacySetting, decimal>(LegacySkinConfiguration.LegacySetting.Version)?.Value == 1.0m); AddAssert("Check legacy version lookup", () => requester.GetConfig<SkinConfiguration.LegacySetting, decimal>(SkinConfiguration.LegacySetting.Version)?.Value == 1.0m);
} }
public enum LookupType public enum LookupType

View File

@ -0,0 +1,110 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System.Linq;
using NUnit.Framework;
using osu.Framework.Graphics;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Drawables;
using osu.Game.Online.API.Requests.Responses;
using osuTK;
namespace osu.Game.Tests.Visual.Beatmaps
{
public class TestSceneDifficultySpectrumDisplay : OsuTestScene
{
private DifficultySpectrumDisplay display;
private static APIBeatmapSet createBeatmapSetWith(params (int rulesetId, double stars)[] difficulties) => new APIBeatmapSet
{
Beatmaps = difficulties.Select(difficulty => new APIBeatmap
{
RulesetID = difficulty.rulesetId,
StarRating = difficulty.stars
}).ToList()
};
[Test]
public void TestSingleRuleset()
{
var beatmapSet = createBeatmapSetWith(
(rulesetId: 0, stars: 2.0),
(rulesetId: 0, stars: 3.2),
(rulesetId: 0, stars: 5.6));
createDisplay(beatmapSet);
}
[Test]
public void TestMultipleRulesets()
{
var beatmapSet = createBeatmapSetWith(
(rulesetId: 0, stars: 2.0),
(rulesetId: 3, stars: 2.3),
(rulesetId: 0, stars: 3.2),
(rulesetId: 1, stars: 4.3),
(rulesetId: 0, stars: 5.6));
createDisplay(beatmapSet);
}
[Test]
public void TestUnknownRuleset()
{
var beatmapSet = createBeatmapSetWith(
(rulesetId: 0, stars: 2.0),
(rulesetId: 3, stars: 2.3),
(rulesetId: 0, stars: 3.2),
(rulesetId: 1, stars: 4.3),
(rulesetId: 0, stars: 5.6),
(rulesetId: 15, stars: 7.8));
createDisplay(beatmapSet);
}
[Test]
public void TestMaximumUncollapsed()
{
var beatmapSet = createBeatmapSetWith(Enumerable.Range(0, 12).Select(i => (rulesetId: i % 4, stars: 2.5 + i * 0.25)).ToArray());
createDisplay(beatmapSet);
}
[Test]
public void TestMinimumCollapsed()
{
var beatmapSet = createBeatmapSetWith(Enumerable.Range(0, 13).Select(i => (rulesetId: i % 4, stars: 2.5 + i * 0.25)).ToArray());
createDisplay(beatmapSet);
}
[Test]
public void TestAdjustableDotSize()
{
var beatmapSet = createBeatmapSetWith(
(rulesetId: 0, stars: 2.0),
(rulesetId: 3, stars: 2.3),
(rulesetId: 0, stars: 3.2),
(rulesetId: 1, stars: 4.3),
(rulesetId: 0, stars: 5.6));
createDisplay(beatmapSet);
AddStep("change dot dimensions", () =>
{
display.DotSize = new Vector2(8, 12);
display.DotSpacing = 2;
});
AddStep("change dot dimensions back", () =>
{
display.DotSize = new Vector2(4, 8);
display.DotSpacing = 1;
});
}
private void createDisplay(IBeatmapSetInfo beatmapSetInfo) => AddStep("create spectrum display", () => Child = display = new DifficultySpectrumDisplay(beatmapSetInfo)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Scale = new Vector2(3)
});
}
}

View File

@ -72,7 +72,7 @@ namespace osu.Game.Tests.Visual.Editing
private Vector2 getPositionForDivisor(int divisor) private Vector2 getPositionForDivisor(int divisor)
{ {
var relativePosition = (float)Math.Clamp(divisor, 0, 16) / 16; float relativePosition = (float)Math.Clamp(divisor, 0, 16) / 16;
var sliderDrawQuad = tickSliderBar.ScreenSpaceDrawQuad; var sliderDrawQuad = tickSliderBar.ScreenSpaceDrawQuad;
return new Vector2( return new Vector2(
sliderDrawQuad.TopLeft.X + sliderDrawQuad.Width * relativePosition, sliderDrawQuad.TopLeft.X + sliderDrawQuad.Width * relativePosition,

View File

@ -76,7 +76,7 @@ namespace osu.Game.Tests.Visual.Editing
{ {
var setup = Editor.ChildrenOfType<SetupScreen>().First(); var setup = Editor.ChildrenOfType<SetupScreen>().First();
var temp = TestResources.GetTestBeatmapForImport(); string temp = TestResources.GetTestBeatmapForImport();
string extractedFolder = $"{temp}_extracted"; string extractedFolder = $"{temp}_extracted";
Directory.CreateDirectory(extractedFolder); Directory.CreateDirectory(extractedFolder);

View File

@ -57,7 +57,7 @@ namespace osu.Game.Tests.Visual.Gameplay
{ {
showOverlay(); showOverlay();
var retryCount = 0; int retryCount = 0;
AddRepeatStep("Add retry", () => AddRepeatStep("Add retry", () =>
{ {

View File

@ -32,7 +32,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
{ PLAYER_2_ID, new ManualClock() } { PLAYER_2_ID, new ManualClock() }
}; };
foreach (var (userId, _) in clocks) foreach ((int userId, var _) in clocks)
{ {
SpectatorClient.StartPlay(userId, 0); SpectatorClient.StartPlay(userId, 0);
OnlinePlayDependencies.Client.AddUser(new User { Id = userId }); OnlinePlayDependencies.Client.AddUser(new User { Id = userId });
@ -53,7 +53,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("add clock sources", () => AddStep("add clock sources", () =>
{ {
foreach (var (userId, clock) in clocks) foreach ((int userId, var clock) in clocks)
leaderboard.AddClock(userId, clock); leaderboard.AddClock(userId, clock);
}); });
} }

View File

@ -289,7 +289,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
[Test] [Test]
public void TestSpectatingDuringGameplay() public void TestSpectatingDuringGameplay()
{ {
var players = new[] { PLAYER_1_ID, PLAYER_2_ID }; int[] players = { PLAYER_1_ID, PLAYER_2_ID };
start(players); start(players);
sendFrames(players, 300); sendFrames(players, 300);
@ -326,7 +326,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
for (int count = 3; count >= 0; count--) for (int count = 3; count >= 0; count--)
{ {
var id = PLAYER_1_ID + count; int id = PLAYER_1_ID + count;
end(id); end(id);
AddUntilStep($"{id} area grayed", () => getInstance(id).Colour != Color4.White); AddUntilStep($"{id} area grayed", () => getInstance(id).Colour != Color4.White);

View File

@ -582,7 +582,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
// Gameplay runs in real-time, so we need to incrementally check if gameplay has finished in order to not time out. // Gameplay runs in real-time, so we need to incrementally check if gameplay has finished in order to not time out.
for (double i = 1000; i < TestResources.QUICK_BEATMAP_LENGTH; i += 1000) for (double i = 1000; i < TestResources.QUICK_BEATMAP_LENGTH; i += 1000)
{ {
var time = i; double time = i;
AddUntilStep($"wait for time > {i}", () => this.ChildrenOfType<GameplayClockContainer>().SingleOrDefault()?.GameplayClock.CurrentTime > time); AddUntilStep($"wait for time > {i}", () => this.ChildrenOfType<GameplayClockContainer>().SingleOrDefault()?.GameplayClock.CurrentTime > time);
} }

View File

@ -55,7 +55,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
var playableBeatmap = Beatmap.Value.GetPlayableBeatmap(Ruleset.Value); var playableBeatmap = Beatmap.Value.GetPlayableBeatmap(Ruleset.Value);
var multiplayerUsers = new List<MultiplayerRoomUser>(); var multiplayerUsers = new List<MultiplayerRoomUser>();
foreach (var user in users) foreach (int user in users)
{ {
SpectatorClient.StartPlay(user, Beatmap.Value.BeatmapInfo.OnlineBeatmapID ?? 0); SpectatorClient.StartPlay(user, Beatmap.Value.BeatmapInfo.OnlineBeatmapID ?? 0);
multiplayerUsers.Add(OnlinePlayDependencies.Client.AddUser(new User { Id = user }, true)); multiplayerUsers.Add(OnlinePlayDependencies.Client.AddUser(new User { Id = user }, true));
@ -89,7 +89,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
[Test] [Test]
public void TestUserQuit() public void TestUserQuit()
{ {
foreach (var user in users) foreach (int user in users)
AddStep($"mark user {user} quit", () => Client.RemoveUser(LookupCache.GetUserAsync(user).Result.AsNonNull())); AddStep($"mark user {user} quit", () => Client.RemoveUser(LookupCache.GetUserAsync(user).Result.AsNonNull()));
} }
@ -114,7 +114,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
public void RandomlyUpdateState() public void RandomlyUpdateState()
{ {
foreach (var userId in PlayingUsers) foreach (int userId in PlayingUsers)
{ {
if (RNG.NextBool()) if (RNG.NextBool())
continue; continue;

View File

@ -59,7 +59,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
var playableBeatmap = Beatmap.Value.GetPlayableBeatmap(Ruleset.Value); var playableBeatmap = Beatmap.Value.GetPlayableBeatmap(Ruleset.Value);
var multiplayerUsers = new List<MultiplayerRoomUser>(); var multiplayerUsers = new List<MultiplayerRoomUser>();
foreach (var user in users) foreach (int user in users)
{ {
SpectatorClient.StartPlay(user, Beatmap.Value.BeatmapInfo.OnlineBeatmapID ?? 0); SpectatorClient.StartPlay(user, Beatmap.Value.BeatmapInfo.OnlineBeatmapID ?? 0);
var roomUser = OnlinePlayDependencies.Client.AddUser(new User { Id = user }, true); var roomUser = OnlinePlayDependencies.Client.AddUser(new User { Id = user }, true);

View File

@ -112,7 +112,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddRepeatStep("increment progress", () => AddRepeatStep("increment progress", () =>
{ {
var progress = this.ChildrenOfType<ParticipantPanel>().Single().User.BeatmapAvailability.DownloadProgress ?? 0; float progress = this.ChildrenOfType<ParticipantPanel>().Single().User.BeatmapAvailability.DownloadProgress ?? 0;
Client.ChangeBeatmapAvailability(BeatmapAvailability.Downloading(progress + RNG.NextSingle(0.1f))); Client.ChangeBeatmapAvailability(BeatmapAvailability.Downloading(progress + RNG.NextSingle(0.1f)));
}, 25); }, 25);

View File

@ -90,7 +90,7 @@ namespace osu.Game.Tests.Visual.Online
{ {
AddAssert("is visible", () => overlay.State.Value == Visibility.Visible); AddAssert("is visible", () => overlay.State.Value == Visibility.Visible);
AddStep("show many results", () => fetchFor(Enumerable.Repeat(CreateAPIBeatmapSet(Ruleset.Value), 10).ToArray())); AddStep("show many results", () => fetchFor(Enumerable.Repeat(CreateAPIBeatmapSet(Ruleset.Value), 100).ToArray()));
AddUntilStep("placeholder hidden", () => !overlay.ChildrenOfType<BeatmapListingOverlay.NotFoundDrawable>().Any(d => d.IsPresent)); AddUntilStep("placeholder hidden", () => !overlay.ChildrenOfType<BeatmapListingOverlay.NotFoundDrawable>().Any(d => d.IsPresent));

View File

@ -190,8 +190,8 @@ namespace osu.Game.Tests.Visual.Online
for (int zeroBasedIndex = 0; zeroBasedIndex < 10; ++zeroBasedIndex) for (int zeroBasedIndex = 0; zeroBasedIndex < 10; ++zeroBasedIndex)
{ {
var oneBasedIndex = zeroBasedIndex + 1; int oneBasedIndex = zeroBasedIndex + 1;
var targetNumberKey = oneBasedIndex % 10; int targetNumberKey = oneBasedIndex % 10;
var targetChannel = channels[zeroBasedIndex]; var targetChannel = channels[zeroBasedIndex];
AddStep($"Press Alt+{targetNumberKey}", () => pressChannelHotkey(targetNumberKey)); AddStep($"Press Alt+{targetNumberKey}", () => pressChannelHotkey(targetNumberKey));
AddAssert($"Channel #{oneBasedIndex} is selected", () => currentChannel == targetChannel); AddAssert($"Channel #{oneBasedIndex} is selected", () => currentChannel == targetChannel);

View File

@ -24,10 +24,10 @@ namespace osu.Game.Tests.Visual.Online
{ {
RankGraph graph; RankGraph graph;
var data = new int[89]; int[] data = new int[89];
var dataWithZeros = new int[89]; int[] dataWithZeros = new int[89];
var smallData = new int[89]; int[] smallData = new int[89];
var edgyData = new int[89]; int[] edgyData = new int[89];
for (int i = 0; i < 89; i++) for (int i = 0; i < 89; i++)
data[i] = dataWithZeros[i] = (i + 1) * 1000; data[i] = dataWithZeros[i] = (i + 1) * 1000;

View File

@ -171,7 +171,7 @@ namespace osu.Game.Tests.Visual.Online
{ {
var indices = chatDisplay.FillFlow.OfType<DrawableChannel.DaySeparator>().Select(ds => chatDisplay.FillFlow.IndexOf(ds)); var indices = chatDisplay.FillFlow.OfType<DrawableChannel.DaySeparator>().Select(ds => chatDisplay.FillFlow.IndexOf(ds));
foreach (var i in indices) foreach (int i in indices)
{ {
if (i < chatDisplay.FillFlow.Count && chatDisplay.FillFlow[i + 1] is DrawableChannel.DaySeparator) if (i < chatDisplay.FillFlow.Count && chatDisplay.FillFlow[i + 1] is DrawableChannel.DaySeparator)
return false; return false;

View File

@ -75,7 +75,7 @@ namespace osu.Game.Tests.Visual.Online
private bool checkBreadcrumb() private bool checkBreadcrumb()
{ {
var result = header.TabControlItems.Contains(wikiPageData.Value.Title); bool result = header.TabControlItems.Contains(wikiPageData.Value.Title);
if (wikiPageData.Value.Subtitle != null) if (wikiPageData.Value.Subtitle != null)
result = header.TabControlItems.Contains(wikiPageData.Value.Subtitle) && result; result = header.TabControlItems.Contains(wikiPageData.Value.Subtitle) && result;

View File

@ -36,7 +36,7 @@ namespace osu.Game.Tests.Visual.Online
{ {
AddStep("Add TOC", () => AddStep("Add TOC", () =>
{ {
for (var i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
addTitle($"This is a very long title {i + 1}"); addTitle($"This is a very long title {i + 1}");
}); });
} }
@ -46,7 +46,7 @@ namespace osu.Game.Tests.Visual.Online
{ {
AddStep("Add TOC", () => AddStep("Add TOC", () =>
{ {
for (var i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
addTitle($"This is a very long title {i + 1}", i % 4 != 0); addTitle($"This is a very long title {i + 1}", i % 4 != 0);
}); });
} }

View File

@ -31,18 +31,18 @@ namespace osu.Game.Tests.Visual.UserInterface
[Test] [Test]
public void TestAddAndRemoveItem() public void TestAddAndRemoveItem()
{ {
foreach (var item in items.Skip(1)) foreach (string item in items.Skip(1))
AddStep($"Add {item} item", () => header.AddItem(item)); AddStep($"Add {item} item", () => header.AddItem(item));
foreach (var item in items.Reverse().SkipLast(3)) foreach (string item in items.Reverse().SkipLast(3))
AddStep($"Remove {item} item", () => header.RemoveItem(item)); AddStep($"Remove {item} item", () => header.RemoveItem(item));
AddStep("Clear items", () => header.ClearItems()); AddStep("Clear items", () => header.ClearItems());
foreach (var item in items) foreach (string item in items)
AddStep($"Add {item} item", () => header.AddItem(item)); AddStep($"Add {item} item", () => header.AddItem(item));
foreach (var item in items) foreach (string item in items)
AddStep($"Remove {item} item", () => header.RemoveItem(item)); AddStep($"Remove {item} item", () => header.RemoveItem(item));
} }

View File

@ -73,8 +73,8 @@ namespace osu.Game.Tests.Visual.UserInterface
private bool assertModsMultiplier(IEnumerable<Mod> mods) private bool assertModsMultiplier(IEnumerable<Mod> mods)
{ {
var multiplier = mods.Aggregate(1.0, (current, mod) => current * mod.ScoreMultiplier); double multiplier = mods.Aggregate(1.0, (current, mod) => current * mod.ScoreMultiplier);
var expectedValue = multiplier.Equals(1.0) ? string.Empty : $"{multiplier:N2}x"; string expectedValue = multiplier.Equals(1.0) ? string.Empty : $"{multiplier:N2}x";
return expectedValue == footerButtonMods.MultiplierText.Current.Value; return expectedValue == footerButtonMods.MultiplierText.Current.Value;
} }

View File

@ -48,7 +48,7 @@ namespace osu.Game.Tests.Visual.UserInterface
foreach (var p in typeof(OsuIcon).GetProperties(BindingFlags.Public | BindingFlags.Static)) foreach (var p in typeof(OsuIcon).GetProperties(BindingFlags.Public | BindingFlags.Static))
{ {
var propValue = p.GetValue(null); object propValue = p.GetValue(null);
Debug.Assert(propValue != null); Debug.Assert(propValue != null);
flow.Add(new Icon($"{nameof(OsuIcon)}.{p.Name}", (IconUsage)propValue)); flow.Add(new Icon($"{nameof(OsuIcon)}.{p.Name}", (IconUsage)propValue));

View File

@ -101,12 +101,12 @@ namespace osu.Game.Tournament.Components
return; return;
} }
var bpm = beatmapInfo.BeatmapSet.OnlineInfo.BPM; double bpm = beatmapInfo.BeatmapSet.OnlineInfo.BPM;
var length = beatmapInfo.Length; double length = beatmapInfo.Length;
string hardRockExtra = ""; string hardRockExtra = "";
string srExtra = ""; string srExtra = "";
var ar = beatmapInfo.BaseDifficulty.ApproachRate; float ar = beatmapInfo.BaseDifficulty.ApproachRate;
if ((mods & LegacyMods.HardRock) > 0) if ((mods & LegacyMods.HardRock) > 0)
{ {
@ -252,9 +252,9 @@ namespace osu.Game.Tournament.Components
s.Font = OsuFont.Torus.With(weight: bold ? FontWeight.Bold : FontWeight.Regular, size: 15); s.Font = OsuFont.Torus.With(weight: bold ? FontWeight.Bold : FontWeight.Regular, size: 15);
} }
for (var i = 0; i < tuples.Length; i++) for (int i = 0; i < tuples.Length; i++)
{ {
var (heading, content) = tuples[i]; (string heading, string content) = tuples[i];
if (i > 0) if (i > 0)
{ {

View File

@ -46,7 +46,7 @@ namespace osu.Game.Tournament.IPC
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {
var stablePath = stableInfo.StablePath ?? findStablePath(); string stablePath = stableInfo.StablePath ?? findStablePath();
initialiseIPCStorage(stablePath); initialiseIPCStorage(stablePath);
} }
@ -78,8 +78,8 @@ namespace osu.Game.Tournament.IPC
using (var stream = IPCStorage.GetStream(file_ipc_filename)) using (var stream = IPCStorage.GetStream(file_ipc_filename))
using (var sr = new StreamReader(stream)) using (var sr = new StreamReader(stream))
{ {
var beatmapId = int.Parse(sr.ReadLine().AsNonNull()); int beatmapId = int.Parse(sr.ReadLine().AsNonNull());
var mods = int.Parse(sr.ReadLine().AsNonNull()); int mods = int.Parse(sr.ReadLine().AsNonNull());
if (lastBeatmapId != beatmapId) if (lastBeatmapId != beatmapId)
{ {
@ -187,7 +187,7 @@ namespace osu.Game.Tournament.IPC
[CanBeNull] [CanBeNull]
private string findStablePath() private string findStablePath()
{ {
var stableInstallPath = findFromEnvVar() ?? string stableInstallPath = findFromEnvVar() ??
findFromRegistry() ?? findFromRegistry() ??
findFromLocalAppData() ?? findFromLocalAppData() ??
findFromDotFolder(); findFromDotFolder();

Some files were not shown because too many files have changed in this diff Show More