1
0
mirror of https://github.com/ppy/osu.git synced 2026-06-04 21:35:44 +08:00

Compare commits

...

70 Commits

216 changed files with 6815 additions and 1620 deletions
+2 -2
View File
@@ -10,7 +10,7 @@
"rollForward": false
},
"codefilesanity": {
"version": "0.0.37",
"version": "0.0.41",
"commands": [
"CodeFileSanity"
],
@@ -24,4 +24,4 @@
"rollForward": false
}
}
}
}
+4
View File
@@ -2,6 +2,10 @@
Thank you for showing interest in the development of osu!. We aim to provide a good collaborating environment for everyone involved, and as such have decided to list some of the most important things to keep in mind in the process. The guidelines below have been chosen based on past experience.
## Foreword on AI usage
Our team believes in **human contributions**. Any contribution be it an issue report or a pull request which is created by, documented by, or aided by AI/LLM usage will typically be **closed and locked without further discussion**.
## Table of contents
1. [Reporting bugs](#reporting-bugs)
+2
View File
@@ -138,6 +138,8 @@ If you wish to help with localisation efforts, head over to [crowdin](https://cr
We love to reward quality contributions. If you have made a large contribution, or are a regular contributor, you are welcome to [submit an expense via opencollective](https://opencollective.com/ppy/expenses/new). If you have any questions, feel free to [reach out to peppy](mailto:pe@ppy.sh) before doing so.
Our team believes in **human contributions**. Any contribution be it an issue report or a pull request which is created by, documented by, or aided by AI/LLM usage will typically be **closed and locked without further discussion**.
## Licence
*osu!*'s code and framework are licensed under the [MIT licence](https://opensource.org/licenses/MIT). Please see [the licence file](LICENCE) for more information. [tl;dr](https://tldrlegal.com/license/mit-license) you can do whatever you want as long as you include the original copyright and license notice in any copy of the software/source.
+1 -1
View File
@@ -10,7 +10,7 @@
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="ppy.osu.Framework.Android" Version="2026.318.0" />
<PackageReference Include="ppy.osu.Framework.Android" Version="2026.416.0" />
</ItemGroup>
<PropertyGroup>
<!-- Fody does not handle Android build well, and warns when unchanged.
+1 -1
View File
@@ -190,7 +190,7 @@ namespace osu.Desktop
}
// user party
if (!hideIdentifiableInformation && multiplayerClient.Room != null && multiplayerClient.Room.Settings.MatchType != MatchType.Matchmaking)
if (!hideIdentifiableInformation && multiplayerClient.Room != null && !multiplayerClient.Room.Settings.MatchType.IsMatchmakingType())
{
MultiplayerRoom room = multiplayerClient.Room;
@@ -0,0 +1,13 @@
// 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 Newtonsoft.Json;
namespace osu.Desktop.IPC.Messages
{
public class HitCountMessage : OsuWebSocketMessage
{
[JsonProperty("new_hits")]
public long NewHits { get; init; }
}
}
@@ -0,0 +1,19 @@
// 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 Newtonsoft.Json;
using osu.Framework.Extensions.TypeExtensions;
namespace osu.Desktop.IPC.Messages
{
public abstract class OsuWebSocketMessage
{
[JsonProperty("type")]
public string Type { get; }
protected OsuWebSocketMessage()
{
Type = GetType().ReadableName();
}
}
}
+75
View File
@@ -0,0 +1,75 @@
// 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;
using System.Linq;
using System.Threading;
using osu.Desktop.IPC.Messages;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Extensions;
using osu.Framework.Graphics;
using osu.Framework.Logging;
using osu.Game.Configuration;
using osu.Game.IPC;
using osu.Game.Online.Multiplayer;
using osu.Game.Rulesets.Scoring;
using osu.Game.Scoring;
using JsonConvert = Newtonsoft.Json.JsonConvert;
namespace osu.Desktop.IPC
{
public partial class OsuWebSocketProvider : Component
{
private WebSocketServer? server;
private readonly Bindable<ScoreInfo> lastLocalScore = new Bindable<ScoreInfo>();
[BackgroundDependencyLoader]
private void load(SessionStatics sessionStatics)
{
server = new WebSocketServer(49727);
server.StartAsync().FireAndForget(onError: ex => Logger.Error(ex, "Failed to start websocket"));
sessionStatics.BindWith(Static.LastLocalUserScore, lastLocalScore);
}
protected override void LoadComplete()
{
base.LoadComplete();
lastLocalScore.BindValueChanged(val =>
{
if (val.NewValue == null)
return;
if (server?.IsRunning != true)
return;
var msg = new HitCountMessage { NewHits = val.NewValue.Statistics.Where(kv => kv.Key.IsBasic() && kv.Key.IsHit()).Sum(kv => kv.Value) };
broadcast(msg);
});
}
private void broadcast(OsuWebSocketMessage message)
{
if (server?.IsRunning != true)
return;
string messageString = JsonConvert.SerializeObject(message);
server.BroadcastAsync(messageString).FireAndForget();
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
if (server?.IsRunning == true)
{
var cts = new CancellationTokenSource();
cts.CancelAfter(TimeSpan.FromSeconds(10));
server.StopAsync(cts.Token).WaitSafely();
server = null;
}
}
}
}
+6
View File
@@ -6,6 +6,7 @@ using System.IO;
using System.Reflection;
using System.Runtime.Versioning;
using Microsoft.Win32;
using osu.Desktop.IPC;
using osu.Desktop.Performance;
using osu.Desktop.Security;
using osu.Framework.Platform;
@@ -35,6 +36,8 @@ namespace osu.Desktop
public bool IsFirstRun { get; init; }
public bool EnableWebSocketServer { get; init; }
public OsuGameDesktop(string[]? args = null)
: base(args)
{
@@ -148,6 +151,9 @@ namespace osu.Desktop
osuSchemeLinkIPCChannel = new OsuSchemeLinkIPCChannel(Host, this);
archiveImportIPCChannel = new ArchiveImportIPCChannel(Host, this);
if (EnableWebSocketServer)
Add(new OsuWebSocketProvider());
}
public override void SetHost(GameHost host)
+2 -1
View File
@@ -140,7 +140,8 @@ namespace osu.Desktop
{
host.Run(new OsuGameDesktop(args)
{
IsFirstRun = isFirstRun
IsFirstRun = isFirstRun,
EnableWebSocketServer = Environment.GetEnvironmentVariable("OSU_WEBSOCKET_SERVER") == "1",
});
}
}
@@ -18,6 +18,7 @@ namespace osu.Game.Rulesets.Catch.Edit.Blueprints.Components
private readonly Path drawablePath;
private readonly List<(double Time, float X)> vertices = new List<(double, float)>();
private readonly List<Vector2> sliderVertices = new List<Vector2>();
public ScrollingPath()
{
@@ -47,9 +48,8 @@ namespace osu.Game.Rulesets.Catch.Edit.Blueprints.Components
private void computeTimeXs(JuiceStream hitObject)
{
vertices.Clear();
var sliderVertices = new List<Vector2>();
hitObject.Path.GetPathToProgress(sliderVertices, 0, 1);
sliderVertices.Clear();
sliderVertices.AddRange(hitObject.Path.CalculatedPath);
if (sliderVertices.Count == 0)
return;
@@ -175,8 +175,7 @@ namespace osu.Game.Rulesets.Catch.Objects
/// </remarks>
public void ConvertFromSliderPath(SliderPath sliderPath, double velocity)
{
var sliderPathVertices = new List<Vector2>();
sliderPath.GetPathToProgress(sliderPathVertices, 0, 1);
var sliderPathVertices = sliderPath.CalculatedPath;
double time = 0;
@@ -19,6 +19,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj" />
<ProjectReference Include="..\osu.Game.Tests\osu.Game.Tests.csproj" />
<ProjectReference Include="..\osu.Game\osu.Game.csproj" />
</ItemGroup>
</Project>
@@ -13,6 +13,7 @@
</Compile>
</ItemGroup>
<ItemGroup Label="Project References">
<ProjectReference Include="..\osu.Game.Tests\osu.Game.Tests.csproj" />
<ProjectReference Include="..\osu.Game\osu.Game.csproj" />
<ProjectReference Include="..\osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj" />
</ItemGroup>
@@ -27,6 +27,24 @@ namespace osu.Game.Rulesets.Mania.Tests
[TestCase("100374")]
[TestCase("1450162")]
[TestCase("4869637")]
[TestCase("1K")]
[TestCase("2K")]
[TestCase("3K")]
[TestCase("4K")]
[TestCase("5K")]
[TestCase("6K")]
[TestCase("7K")]
[TestCase("8K")]
[TestCase("9K")]
[TestCase("10K")]
// [TestCase("11K")] <- See comment in `ManiaBeatmapConverter` ctor for disable reason.
[TestCase("12K")]
// [TestCase("13K")] <- See comment in `ManiaBeatmapConverter` ctor for disable reason.
[TestCase("14K")]
// [TestCase("15K")] <- See comment in `ManiaBeatmapConverter` ctor for disable reason.
[TestCase("16K")]
// [TestCase("17K")] <- See comment in `ManiaBeatmapConverter` ctor for disable reason.
[TestCase("18K")]
public void Test(string name) => base.Test(name);
protected override IEnumerable<ConvertValue> CreateConvertValue(HitObject hitObject)
@@ -0,0 +1,45 @@
// 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 NUnit.Framework;
using osu.Framework.IO.Stores;
using static osu.Game.Tests.Beatmaps.Formats.LegacyBeatmapEncoderTest;
namespace osu.Game.Rulesets.Mania.Tests
{
[TestFixture]
public class ManiaLegacyBeatmapEncoderTest
{
private static readonly DllResourceStore beatmaps_resource_store = new DllResourceStore(typeof(ManiaLegacyBeatmapEncoderTest).Assembly);
[TestCase("1K")]
[TestCase("2K")]
[TestCase("3K")]
[TestCase("4K")]
[TestCase("5K")]
[TestCase("6K")]
[TestCase("7K")]
[TestCase("8K")]
[TestCase("9K")]
[TestCase("10K")]
// [TestCase("11K")] <- See comment in `ManiaBeatmapConverter` ctor for disable reason.
[TestCase("12K")]
// [TestCase("13K")] <- See comment in `ManiaBeatmapConverter` ctor for disable reason.
[TestCase("14K")]
// [TestCase("15K")] <- See comment in `ManiaBeatmapConverter` ctor for disable reason.
[TestCase("16K")]
// [TestCase("17K")] <- See comment in `ManiaBeatmapConverter` ctor for disable reason.
[TestCase("18K")]
[TestCase("7K+1")]
public void TestEncodeDecodeStability(string name)
{
var decoded = DecodeFromLegacy(beatmaps_resource_store.GetStream($"Resources/Testing/Beatmaps/{name}.osu"), beatmaps_resource_store, name);
var decodedAfterEncode = DecodeFromLegacy(EncodeToLegacy(decoded), beatmaps_resource_store, name);
Sort(decoded.beatmap);
Sort(decodedAfterEncode.beatmap);
CompareBeatmaps(decoded, decodedAfterEncode);
}
}
}
@@ -25,6 +25,8 @@ namespace osu.Game.Rulesets.Mania.Tests.Mods
{
public partial class TestSceneManiaModNoRelease : RateAdjustedBeatmapTestScene
{
protected override Ruleset CreateRuleset() => new ManiaRuleset();
private const double time_before_head = 250;
private const double time_head = 1500;
private const double time_during_hold_1 = 2500;
@@ -0,0 +1 @@
{"Mappings":[{"RandomW":273326509,"RandomX":511,"RandomY":842502087,"RandomZ":3579807591,"StartTime":0.0,"Objects":[{"StartTime":0.0,"EndTime":0.0,"Column":0}]},{"RandomW":273326509,"RandomX":511,"RandomY":842502087,"RandomZ":3579807591,"StartTime":125.0,"Objects":[{"StartTime":125.0,"EndTime":125.0,"Column":1}]},{"RandomW":273326509,"RandomX":511,"RandomY":842502087,"RandomZ":3579807591,"StartTime":250.0,"Objects":[{"StartTime":250.0,"EndTime":250.0,"Column":2}]},{"RandomW":273326509,"RandomX":511,"RandomY":842502087,"RandomZ":3579807591,"StartTime":375.0,"Objects":[{"StartTime":375.0,"EndTime":375.0,"Column":3}]},{"RandomW":273326509,"RandomX":511,"RandomY":842502087,"RandomZ":3579807591,"StartTime":500.0,"Objects":[{"StartTime":500.0,"EndTime":500.0,"Column":4}]},{"RandomW":273326509,"RandomX":511,"RandomY":842502087,"RandomZ":3579807591,"StartTime":625.0,"Objects":[{"StartTime":625.0,"EndTime":625.0,"Column":5}]},{"RandomW":273326509,"RandomX":511,"RandomY":842502087,"RandomZ":3579807591,"StartTime":750.0,"Objects":[{"StartTime":750.0,"EndTime":750.0,"Column":6}]},{"RandomW":273326509,"RandomX":511,"RandomY":842502087,"RandomZ":3579807591,"StartTime":875.0,"Objects":[{"StartTime":875.0,"EndTime":875.0,"Column":7}]},{"RandomW":273326509,"RandomX":511,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1000.0,"Objects":[{"StartTime":1000.0,"EndTime":1000.0,"Column":8}]},{"RandomW":273326509,"RandomX":511,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1125.0,"Objects":[{"StartTime":1125.0,"EndTime":1125.0,"Column":9}]}]}
@@ -0,0 +1,46 @@
osu file format v14
[General]
Mode: 3
[Metadata]
Title:keycount test
TitleUnicode:keycount test
Artist:mania
ArtistUnicode:mania
Creator:spaceman_atlas
Version:10K
[Difficulty]
HPDrainRate:5
CircleSize:10
OverallDifficulty:5
ApproachRate:5
SliderMultiplier:1.4
SliderTickRate:1
[Events]
//Background and Video events
//Break Periods
//Storyboard Layer 0 (Background)
//Storyboard Layer 1 (Fail)
//Storyboard Layer 2 (Pass)
//Storyboard Layer 3 (Foreground)
//Storyboard Layer 4 (Overlay)
//Storyboard Sound Samples
[TimingPoints]
0,500,4,2,0,100,1,0
[HitObjects]
25,192,0,1,0,0:0:0:0:
76,192,125,1,0,0:0:0:0:
128,192,250,1,0,0:0:0:0:
179,192,375,1,0,0:0:0:0:
230,192,500,1,0,0:0:0:0:
281,192,625,1,0,0:0:0:0:
332,192,750,1,0,0:0:0:0:
384,192,875,1,0,0:0:0:0:
435,192,1000,1,0,0:0:0:0:
486,192,1125,1,0,0:0:0:0:
@@ -0,0 +1 @@
{"Mappings":[{"RandomW":273326509,"RandomX":531,"RandomY":842502087,"RandomZ":3579807591,"StartTime":0.0,"Objects":[{"StartTime":0.0,"EndTime":0.0,"Column":0}]},{"RandomW":273326509,"RandomX":531,"RandomY":842502087,"RandomZ":3579807591,"StartTime":125.0,"Objects":[{"StartTime":125.0,"EndTime":125.0,"Column":1}]},{"RandomW":273326509,"RandomX":531,"RandomY":842502087,"RandomZ":3579807591,"StartTime":250.0,"Objects":[{"StartTime":250.0,"EndTime":250.0,"Column":2}]},{"RandomW":273326509,"RandomX":531,"RandomY":842502087,"RandomZ":3579807591,"StartTime":375.0,"Objects":[{"StartTime":375.0,"EndTime":375.0,"Column":3}]},{"RandomW":273326509,"RandomX":531,"RandomY":842502087,"RandomZ":3579807591,"StartTime":500.0,"Objects":[{"StartTime":500.0,"EndTime":500.0,"Column":4}]},{"RandomW":273326509,"RandomX":531,"RandomY":842502087,"RandomZ":3579807591,"StartTime":625.0,"Objects":[{"StartTime":625.0,"EndTime":625.0,"Column":5}]},{"RandomW":273326509,"RandomX":531,"RandomY":842502087,"RandomZ":3579807591,"StartTime":750.0,"Objects":[{"StartTime":750.0,"EndTime":750.0,"Column":6}]},{"RandomW":273326509,"RandomX":531,"RandomY":842502087,"RandomZ":3579807591,"StartTime":875.0,"Objects":[{"StartTime":875.0,"EndTime":875.0,"Column":7}]},{"RandomW":273326509,"RandomX":531,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1000.0,"Objects":[{"StartTime":1000.0,"EndTime":1000.0,"Column":8}]},{"RandomW":273326509,"RandomX":531,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1125.0,"Objects":[{"StartTime":1125.0,"EndTime":1125.0,"Column":9}]},{"RandomW":273326509,"RandomX":531,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1250.0,"Objects":[{"StartTime":1250.0,"EndTime":1250.0,"Column":10}]}]}
@@ -0,0 +1,47 @@
osu file format v14
[General]
Mode: 3
[Metadata]
Title:keycount test
TitleUnicode:keycount test
Artist:mania
ArtistUnicode:mania
Creator:spaceman_atlas
Version:11K
[Difficulty]
HPDrainRate:5
CircleSize:11
OverallDifficulty:5
ApproachRate:5
SliderMultiplier:1.4
SliderTickRate:1
[Events]
//Background and Video events
//Break Periods
//Storyboard Layer 0 (Background)
//Storyboard Layer 1 (Fail)
//Storyboard Layer 2 (Pass)
//Storyboard Layer 3 (Foreground)
//Storyboard Layer 4 (Overlay)
//Storyboard Sound Samples
[TimingPoints]
0,500,4,2,0,100,1,0
[HitObjects]
23,192,0,1,0,0:0:0:0:
69,192,125,1,0,0:0:0:0:
116,192,250,1,0,0:0:0:0:
162,192,375,1,0,0:0:0:0:
209,192,500,1,0,0:0:0:0:
256,192,625,1,0,0:0:0:0:
302,192,750,1,0,0:0:0:0:
349,192,875,1,0,0:0:0:0:
395,192,1000,1,0,0:0:0:0:
442,192,1125,1,0,0:0:0:0:
488,192,1250,1,0,0:0:0:0:
@@ -0,0 +1 @@
{"Mappings":[{"RandomW":273326509,"RandomX":551,"RandomY":842502087,"RandomZ":3579807591,"StartTime":0.0,"Objects":[{"StartTime":0.0,"EndTime":0.0,"Column":0}]},{"RandomW":273326509,"RandomX":551,"RandomY":842502087,"RandomZ":3579807591,"StartTime":125.0,"Objects":[{"StartTime":125.0,"EndTime":125.0,"Column":1}]},{"RandomW":273326509,"RandomX":551,"RandomY":842502087,"RandomZ":3579807591,"StartTime":250.0,"Objects":[{"StartTime":250.0,"EndTime":250.0,"Column":2}]},{"RandomW":273326509,"RandomX":551,"RandomY":842502087,"RandomZ":3579807591,"StartTime":375.0,"Objects":[{"StartTime":375.0,"EndTime":375.0,"Column":3}]},{"RandomW":273326509,"RandomX":551,"RandomY":842502087,"RandomZ":3579807591,"StartTime":500.0,"Objects":[{"StartTime":500.0,"EndTime":500.0,"Column":4}]},{"RandomW":273326509,"RandomX":551,"RandomY":842502087,"RandomZ":3579807591,"StartTime":625.0,"Objects":[{"StartTime":625.0,"EndTime":625.0,"Column":5}]},{"RandomW":273326509,"RandomX":551,"RandomY":842502087,"RandomZ":3579807591,"StartTime":750.0,"Objects":[{"StartTime":750.0,"EndTime":750.0,"Column":6}]},{"RandomW":273326509,"RandomX":551,"RandomY":842502087,"RandomZ":3579807591,"StartTime":875.0,"Objects":[{"StartTime":875.0,"EndTime":875.0,"Column":7}]},{"RandomW":273326509,"RandomX":551,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1000.0,"Objects":[{"StartTime":1000.0,"EndTime":1000.0,"Column":8}]},{"RandomW":273326509,"RandomX":551,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1125.0,"Objects":[{"StartTime":1125.0,"EndTime":1125.0,"Column":9}]},{"RandomW":273326509,"RandomX":551,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1250.0,"Objects":[{"StartTime":1250.0,"EndTime":1250.0,"Column":10}]},{"RandomW":273326509,"RandomX":551,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1375.0,"Objects":[{"StartTime":1375.0,"EndTime":1375.0,"Column":11}]}]}
@@ -0,0 +1,48 @@
osu file format v14
[General]
Mode: 3
[Metadata]
Title:keycount test
TitleUnicode:keycount test
Artist:mania
ArtistUnicode:mania
Creator:spaceman_atlas
Version:12K
[Difficulty]
HPDrainRate:5
CircleSize:12
OverallDifficulty:5
ApproachRate:5
SliderMultiplier:1.4
SliderTickRate:1
[Events]
//Background and Video events
//Break Periods
//Storyboard Layer 0 (Background)
//Storyboard Layer 1 (Fail)
//Storyboard Layer 2 (Pass)
//Storyboard Layer 3 (Foreground)
//Storyboard Layer 4 (Overlay)
//Storyboard Sound Samples
[TimingPoints]
0,500,4,2,0,100,1,0
[HitObjects]
21,192,0,1,0,0:0:0:0:
64,192,125,1,0,0:0:0:0:
106,192,250,1,0,0:0:0:0:
149,192,375,1,0,0:0:0:0:
192,192,500,1,0,0:0:0:0:
234,192,625,1,0,0:0:0:0:
277,192,750,1,0,0:0:0:0:
320,192,875,1,0,0:0:0:0:
362,192,1000,1,0,0:0:0:0:
405,192,1125,1,0,0:0:0:0:
448,192,1250,1,0,0:0:0:0:
490,192,1375,1,0,0:0:0:0:
@@ -0,0 +1 @@
{"Mappings":[{"RandomW":273326509,"RandomX":571,"RandomY":842502087,"RandomZ":3579807591,"StartTime":0.0,"Objects":[{"StartTime":0.0,"EndTime":0.0,"Column":0}]},{"RandomW":273326509,"RandomX":571,"RandomY":842502087,"RandomZ":3579807591,"StartTime":125.0,"Objects":[{"StartTime":125.0,"EndTime":125.0,"Column":1}]},{"RandomW":273326509,"RandomX":571,"RandomY":842502087,"RandomZ":3579807591,"StartTime":250.0,"Objects":[{"StartTime":250.0,"EndTime":250.0,"Column":2}]},{"RandomW":273326509,"RandomX":571,"RandomY":842502087,"RandomZ":3579807591,"StartTime":375.0,"Objects":[{"StartTime":375.0,"EndTime":375.0,"Column":3}]},{"RandomW":273326509,"RandomX":571,"RandomY":842502087,"RandomZ":3579807591,"StartTime":500.0,"Objects":[{"StartTime":500.0,"EndTime":500.0,"Column":4}]},{"RandomW":273326509,"RandomX":571,"RandomY":842502087,"RandomZ":3579807591,"StartTime":625.0,"Objects":[{"StartTime":625.0,"EndTime":625.0,"Column":5}]},{"RandomW":273326509,"RandomX":571,"RandomY":842502087,"RandomZ":3579807591,"StartTime":750.0,"Objects":[{"StartTime":750.0,"EndTime":750.0,"Column":6}]},{"RandomW":273326509,"RandomX":571,"RandomY":842502087,"RandomZ":3579807591,"StartTime":875.0,"Objects":[{"StartTime":875.0,"EndTime":875.0,"Column":7}]},{"RandomW":273326509,"RandomX":571,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1000.0,"Objects":[{"StartTime":1000.0,"EndTime":1000.0,"Column":8}]},{"RandomW":273326509,"RandomX":571,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1125.0,"Objects":[{"StartTime":1125.0,"EndTime":1125.0,"Column":9}]},{"RandomW":273326509,"RandomX":571,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1250.0,"Objects":[{"StartTime":1250.0,"EndTime":1250.0,"Column":10}]},{"RandomW":273326509,"RandomX":571,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1375.0,"Objects":[{"StartTime":1375.0,"EndTime":1375.0,"Column":11}]},{"RandomW":273326509,"RandomX":571,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1500.0,"Objects":[{"StartTime":1500.0,"EndTime":1500.0,"Column":12}]}]}
@@ -0,0 +1,49 @@
osu file format v14
[General]
Mode: 3
[Metadata]
Title:keycount test
TitleUnicode:keycount test
Artist:mania
ArtistUnicode:mania
Creator:spaceman_atlas
Version:13K
[Difficulty]
HPDrainRate:5
CircleSize:13
OverallDifficulty:5
ApproachRate:5
SliderMultiplier:1.4
SliderTickRate:1
[Events]
//Background and Video events
//Break Periods
//Storyboard Layer 0 (Background)
//Storyboard Layer 1 (Fail)
//Storyboard Layer 2 (Pass)
//Storyboard Layer 3 (Foreground)
//Storyboard Layer 4 (Overlay)
//Storyboard Sound Samples
[TimingPoints]
0,500,4,2,0,100,1,0
[HitObjects]
19,192,0,1,0,0:0:0:0:
59,192,125,1,0,0:0:0:0:
98,192,250,1,0,0:0:0:0:
137,192,375,1,0,0:0:0:0:
177,192,500,1,0,0:0:0:0:
216,192,625,1,0,0:0:0:0:
256,192,750,1,0,0:0:0:0:
295,192,875,1,0,0:0:0:0:
334,192,1000,1,0,0:0:0:0:
374,192,1125,1,0,0:0:0:0:
413,192,1250,1,0,0:0:0:0:
452,192,1375,1,0,0:0:0:0:
492,192,1500,1,0,0:0:0:0:
@@ -0,0 +1 @@
{"Mappings":[{"RandomW":273326509,"RandomX":591,"RandomY":842502087,"RandomZ":3579807591,"StartTime":0.0,"Objects":[{"StartTime":0.0,"EndTime":0.0,"Column":0}]},{"RandomW":273326509,"RandomX":591,"RandomY":842502087,"RandomZ":3579807591,"StartTime":125.0,"Objects":[{"StartTime":125.0,"EndTime":125.0,"Column":1}]},{"RandomW":273326509,"RandomX":591,"RandomY":842502087,"RandomZ":3579807591,"StartTime":250.0,"Objects":[{"StartTime":250.0,"EndTime":250.0,"Column":2}]},{"RandomW":273326509,"RandomX":591,"RandomY":842502087,"RandomZ":3579807591,"StartTime":375.0,"Objects":[{"StartTime":375.0,"EndTime":375.0,"Column":3}]},{"RandomW":273326509,"RandomX":591,"RandomY":842502087,"RandomZ":3579807591,"StartTime":500.0,"Objects":[{"StartTime":500.0,"EndTime":500.0,"Column":4}]},{"RandomW":273326509,"RandomX":591,"RandomY":842502087,"RandomZ":3579807591,"StartTime":625.0,"Objects":[{"StartTime":625.0,"EndTime":625.0,"Column":5}]},{"RandomW":273326509,"RandomX":591,"RandomY":842502087,"RandomZ":3579807591,"StartTime":750.0,"Objects":[{"StartTime":750.0,"EndTime":750.0,"Column":6}]},{"RandomW":273326509,"RandomX":591,"RandomY":842502087,"RandomZ":3579807591,"StartTime":875.0,"Objects":[{"StartTime":875.0,"EndTime":875.0,"Column":7}]},{"RandomW":273326509,"RandomX":591,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1000.0,"Objects":[{"StartTime":1000.0,"EndTime":1000.0,"Column":8}]},{"RandomW":273326509,"RandomX":591,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1125.0,"Objects":[{"StartTime":1125.0,"EndTime":1125.0,"Column":9}]},{"RandomW":273326509,"RandomX":591,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1250.0,"Objects":[{"StartTime":1250.0,"EndTime":1250.0,"Column":10}]},{"RandomW":273326509,"RandomX":591,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1375.0,"Objects":[{"StartTime":1375.0,"EndTime":1375.0,"Column":11}]},{"RandomW":273326509,"RandomX":591,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1500.0,"Objects":[{"StartTime":1500.0,"EndTime":1500.0,"Column":12}]},{"RandomW":273326509,"RandomX":591,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1625.0,"Objects":[{"StartTime":1625.0,"EndTime":1625.0,"Column":13}]}]}
@@ -0,0 +1,50 @@
osu file format v14
[General]
Mode: 3
[Metadata]
Title:keycount test
TitleUnicode:keycount test
Artist:mania
ArtistUnicode:mania
Creator:spaceman_atlas
Version:14K
[Difficulty]
HPDrainRate:5
CircleSize:14
OverallDifficulty:5
ApproachRate:5
SliderMultiplier:1.4
SliderTickRate:1
[Events]
//Background and Video events
//Break Periods
//Storyboard Layer 0 (Background)
//Storyboard Layer 1 (Fail)
//Storyboard Layer 2 (Pass)
//Storyboard Layer 3 (Foreground)
//Storyboard Layer 4 (Overlay)
//Storyboard Sound Samples
[TimingPoints]
0,500,4,2,0,100,1,0
[HitObjects]
18,192,0,1,0,0:0:0:0:
54,192,125,1,0,0:0:0:0:
91,192,250,1,0,0:0:0:0:
128,192,375,1,0,0:0:0:0:
164,192,500,1,0,0:0:0:0:
201,192,625,1,0,0:0:0:0:
237,192,750,1,0,0:0:0:0:
274,192,875,1,0,0:0:0:0:
310,192,1000,1,0,0:0:0:0:
347,192,1125,1,0,0:0:0:0:
384,192,1250,1,0,0:0:0:0:
420,192,1375,1,0,0:0:0:0:
457,192,1500,1,0,0:0:0:0:
493,192,1625,1,0,0:0:0:0:
@@ -0,0 +1 @@
{"Mappings":[{"RandomW":273326509,"RandomX":611,"RandomY":842502087,"RandomZ":3579807591,"StartTime":0.0,"Objects":[{"StartTime":0.0,"EndTime":0.0,"Column":0}]},{"RandomW":273326509,"RandomX":611,"RandomY":842502087,"RandomZ":3579807591,"StartTime":125.0,"Objects":[{"StartTime":125.0,"EndTime":125.0,"Column":1}]},{"RandomW":273326509,"RandomX":611,"RandomY":842502087,"RandomZ":3579807591,"StartTime":250.0,"Objects":[{"StartTime":250.0,"EndTime":250.0,"Column":2}]},{"RandomW":273326509,"RandomX":611,"RandomY":842502087,"RandomZ":3579807591,"StartTime":375.0,"Objects":[{"StartTime":375.0,"EndTime":375.0,"Column":3}]},{"RandomW":273326509,"RandomX":611,"RandomY":842502087,"RandomZ":3579807591,"StartTime":500.0,"Objects":[{"StartTime":500.0,"EndTime":500.0,"Column":4}]},{"RandomW":273326509,"RandomX":611,"RandomY":842502087,"RandomZ":3579807591,"StartTime":625.0,"Objects":[{"StartTime":625.0,"EndTime":625.0,"Column":5}]},{"RandomW":273326509,"RandomX":611,"RandomY":842502087,"RandomZ":3579807591,"StartTime":750.0,"Objects":[{"StartTime":750.0,"EndTime":750.0,"Column":6}]},{"RandomW":273326509,"RandomX":611,"RandomY":842502087,"RandomZ":3579807591,"StartTime":875.0,"Objects":[{"StartTime":875.0,"EndTime":875.0,"Column":7}]},{"RandomW":273326509,"RandomX":611,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1000.0,"Objects":[{"StartTime":1000.0,"EndTime":1000.0,"Column":8}]},{"RandomW":273326509,"RandomX":611,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1125.0,"Objects":[{"StartTime":1125.0,"EndTime":1125.0,"Column":9}]},{"RandomW":273326509,"RandomX":611,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1250.0,"Objects":[{"StartTime":1250.0,"EndTime":1250.0,"Column":10}]},{"RandomW":273326509,"RandomX":611,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1375.0,"Objects":[{"StartTime":1375.0,"EndTime":1375.0,"Column":11}]},{"RandomW":273326509,"RandomX":611,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1500.0,"Objects":[{"StartTime":1500.0,"EndTime":1500.0,"Column":12}]},{"RandomW":273326509,"RandomX":611,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1625.0,"Objects":[{"StartTime":1625.0,"EndTime":1625.0,"Column":13}]},{"RandomW":273326509,"RandomX":611,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1750.0,"Objects":[{"StartTime":1750.0,"EndTime":1750.0,"Column":14}]}]}
@@ -0,0 +1,51 @@
osu file format v14
[General]
Mode: 3
[Metadata]
Title:keycount test
TitleUnicode:keycount test
Artist:mania
ArtistUnicode:mania
Creator:spaceman_atlas
Version:15K
[Difficulty]
HPDrainRate:5
CircleSize:15
OverallDifficulty:5
ApproachRate:5
SliderMultiplier:1.4
SliderTickRate:1
[Events]
//Background and Video events
//Break Periods
//Storyboard Layer 0 (Background)
//Storyboard Layer 1 (Fail)
//Storyboard Layer 2 (Pass)
//Storyboard Layer 3 (Foreground)
//Storyboard Layer 4 (Overlay)
//Storyboard Sound Samples
[TimingPoints]
0,500,4,2,0,100,1,0
[HitObjects]
17,192,0,1,0,0:0:0:0:
51,192,125,1,0,0:0:0:0:
85,192,250,1,0,0:0:0:0:
119,192,375,1,0,0:0:0:0:
153,192,500,1,0,0:0:0:0:
187,192,625,1,0,0:0:0:0:
221,192,750,1,0,0:0:0:0:
256,192,875,1,0,0:0:0:0:
290,192,1000,1,0,0:0:0:0:
324,192,1125,1,0,0:0:0:0:
358,192,1250,1,0,0:0:0:0:
392,192,1375,1,0,0:0:0:0:
426,192,1500,1,0,0:0:0:0:
460,192,1625,1,0,0:0:0:0:
494,192,1750,1,0,0:0:0:0:
@@ -0,0 +1 @@
{"Mappings":[{"RandomW":273326509,"RandomX":631,"RandomY":842502087,"RandomZ":3579807591,"StartTime":0.0,"Objects":[{"StartTime":0.0,"EndTime":0.0,"Column":0}]},{"RandomW":273326509,"RandomX":631,"RandomY":842502087,"RandomZ":3579807591,"StartTime":125.0,"Objects":[{"StartTime":125.0,"EndTime":125.0,"Column":1}]},{"RandomW":273326509,"RandomX":631,"RandomY":842502087,"RandomZ":3579807591,"StartTime":250.0,"Objects":[{"StartTime":250.0,"EndTime":250.0,"Column":2}]},{"RandomW":273326509,"RandomX":631,"RandomY":842502087,"RandomZ":3579807591,"StartTime":375.0,"Objects":[{"StartTime":375.0,"EndTime":375.0,"Column":3}]},{"RandomW":273326509,"RandomX":631,"RandomY":842502087,"RandomZ":3579807591,"StartTime":500.0,"Objects":[{"StartTime":500.0,"EndTime":500.0,"Column":4}]},{"RandomW":273326509,"RandomX":631,"RandomY":842502087,"RandomZ":3579807591,"StartTime":625.0,"Objects":[{"StartTime":625.0,"EndTime":625.0,"Column":5}]},{"RandomW":273326509,"RandomX":631,"RandomY":842502087,"RandomZ":3579807591,"StartTime":750.0,"Objects":[{"StartTime":750.0,"EndTime":750.0,"Column":6}]},{"RandomW":273326509,"RandomX":631,"RandomY":842502087,"RandomZ":3579807591,"StartTime":875.0,"Objects":[{"StartTime":875.0,"EndTime":875.0,"Column":7}]},{"RandomW":273326509,"RandomX":631,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1000.0,"Objects":[{"StartTime":1000.0,"EndTime":1000.0,"Column":8}]},{"RandomW":273326509,"RandomX":631,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1125.0,"Objects":[{"StartTime":1125.0,"EndTime":1125.0,"Column":9}]},{"RandomW":273326509,"RandomX":631,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1250.0,"Objects":[{"StartTime":1250.0,"EndTime":1250.0,"Column":10}]},{"RandomW":273326509,"RandomX":631,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1375.0,"Objects":[{"StartTime":1375.0,"EndTime":1375.0,"Column":11}]},{"RandomW":273326509,"RandomX":631,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1500.0,"Objects":[{"StartTime":1500.0,"EndTime":1500.0,"Column":12}]},{"RandomW":273326509,"RandomX":631,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1625.0,"Objects":[{"StartTime":1625.0,"EndTime":1625.0,"Column":13}]},{"RandomW":273326509,"RandomX":631,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1750.0,"Objects":[{"StartTime":1750.0,"EndTime":1750.0,"Column":14}]},{"RandomW":273326509,"RandomX":631,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1875.0,"Objects":[{"StartTime":1875.0,"EndTime":1875.0,"Column":15}]}]}
@@ -0,0 +1,52 @@
osu file format v14
[General]
Mode: 3
[Metadata]
Title:keycount test
TitleUnicode:keycount test
Artist:mania
ArtistUnicode:mania
Creator:spaceman_atlas
Version:16K
[Difficulty]
HPDrainRate:5
CircleSize:16
OverallDifficulty:5
ApproachRate:5
SliderMultiplier:1.4
SliderTickRate:1
[Events]
//Background and Video events
//Break Periods
//Storyboard Layer 0 (Background)
//Storyboard Layer 1 (Fail)
//Storyboard Layer 2 (Pass)
//Storyboard Layer 3 (Foreground)
//Storyboard Layer 4 (Overlay)
//Storyboard Sound Samples
[TimingPoints]
0,500,4,2,0,100,1,0
[HitObjects]
16,192,0,1,0,0:0:0:0:
48,192,125,1,0,0:0:0:0:
80,192,250,1,0,0:0:0:0:
112,192,375,1,0,0:0:0:0:
144,192,500,1,0,0:0:0:0:
176,192,625,1,0,0:0:0:0:
208,192,750,1,0,0:0:0:0:
240,192,875,1,0,0:0:0:0:
272,192,1000,1,0,0:0:0:0:
304,192,1125,1,0,0:0:0:0:
336,192,1250,1,0,0:0:0:0:
368,192,1375,1,0,0:0:0:0:
400,192,1500,1,0,0:0:0:0:
432,192,1625,1,0,0:0:0:0:
464,192,1750,1,0,0:0:0:0:
496,192,1875,1,0,0:0:0:0:
@@ -0,0 +1 @@
{"Mappings":[{"RandomW":273326509,"RandomX":651,"RandomY":842502087,"RandomZ":3579807591,"StartTime":0.0,"Objects":[{"StartTime":0.0,"EndTime":0.0,"Column":0}]},{"RandomW":273326509,"RandomX":651,"RandomY":842502087,"RandomZ":3579807591,"StartTime":125.0,"Objects":[{"StartTime":125.0,"EndTime":125.0,"Column":1}]},{"RandomW":273326509,"RandomX":651,"RandomY":842502087,"RandomZ":3579807591,"StartTime":250.0,"Objects":[{"StartTime":250.0,"EndTime":250.0,"Column":2}]},{"RandomW":273326509,"RandomX":651,"RandomY":842502087,"RandomZ":3579807591,"StartTime":375.0,"Objects":[{"StartTime":375.0,"EndTime":375.0,"Column":3}]},{"RandomW":273326509,"RandomX":651,"RandomY":842502087,"RandomZ":3579807591,"StartTime":500.0,"Objects":[{"StartTime":500.0,"EndTime":500.0,"Column":4}]},{"RandomW":273326509,"RandomX":651,"RandomY":842502087,"RandomZ":3579807591,"StartTime":625.0,"Objects":[{"StartTime":625.0,"EndTime":625.0,"Column":5}]},{"RandomW":273326509,"RandomX":651,"RandomY":842502087,"RandomZ":3579807591,"StartTime":750.0,"Objects":[{"StartTime":750.0,"EndTime":750.0,"Column":6}]},{"RandomW":273326509,"RandomX":651,"RandomY":842502087,"RandomZ":3579807591,"StartTime":875.0,"Objects":[{"StartTime":875.0,"EndTime":875.0,"Column":7}]},{"RandomW":273326509,"RandomX":651,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1000.0,"Objects":[{"StartTime":1000.0,"EndTime":1000.0,"Column":8}]},{"RandomW":273326509,"RandomX":651,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1125.0,"Objects":[{"StartTime":1125.0,"EndTime":1125.0,"Column":9}]},{"RandomW":273326509,"RandomX":651,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1250.0,"Objects":[{"StartTime":1250.0,"EndTime":1250.0,"Column":10}]},{"RandomW":273326509,"RandomX":651,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1375.0,"Objects":[{"StartTime":1375.0,"EndTime":1375.0,"Column":11}]},{"RandomW":273326509,"RandomX":651,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1500.0,"Objects":[{"StartTime":1500.0,"EndTime":1500.0,"Column":12}]},{"RandomW":273326509,"RandomX":651,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1625.0,"Objects":[{"StartTime":1625.0,"EndTime":1625.0,"Column":13}]},{"RandomW":273326509,"RandomX":651,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1750.0,"Objects":[{"StartTime":1750.0,"EndTime":1750.0,"Column":14}]},{"RandomW":273326509,"RandomX":651,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1875.0,"Objects":[{"StartTime":1875.0,"EndTime":1875.0,"Column":15}]},{"RandomW":273326509,"RandomX":651,"RandomY":842502087,"RandomZ":3579807591,"StartTime":2000.0,"Objects":[{"StartTime":2000.0,"EndTime":2000.0,"Column":16}]}]}
@@ -0,0 +1,53 @@
osu file format v14
[General]
Mode: 3
[Metadata]
Title:keycount test
TitleUnicode:keycount test
Artist:mania
ArtistUnicode:mania
Creator:spaceman_atlas
Version:17K
[Difficulty]
HPDrainRate:5
CircleSize:17
OverallDifficulty:5
ApproachRate:5
SliderMultiplier:1.4
SliderTickRate:1
[Events]
//Background and Video events
//Break Periods
//Storyboard Layer 0 (Background)
//Storyboard Layer 1 (Fail)
//Storyboard Layer 2 (Pass)
//Storyboard Layer 3 (Foreground)
//Storyboard Layer 4 (Overlay)
//Storyboard Sound Samples
[TimingPoints]
0,500,4,2,0,100,1,0
[HitObjects]
15,192,0,1,0,0:0:0:0:
45,192,125,1,0,0:0:0:0:
75,192,250,1,0,0:0:0:0:
105,192,375,1,0,0:0:0:0:
135,192,500,1,0,0:0:0:0:
165,192,625,1,0,0:0:0:0:
195,192,750,1,0,0:0:0:0:
225,192,875,1,0,0:0:0:0:
256,192,1000,1,0,0:0:0:0:
286,192,1125,1,0,0:0:0:0:
316,192,1250,1,0,0:0:0:0:
346,192,1375,1,0,0:0:0:0:
376,192,1500,1,0,0:0:0:0:
406,192,1625,1,0,0:0:0:0:
436,192,1750,1,0,0:0:0:0:
466,192,1875,1,0,0:0:0:0:
496,192,2000,1,0,0:0:0:0:
@@ -0,0 +1 @@
{"Mappings":[{"RandomW":273326509,"RandomX":671,"RandomY":842502087,"RandomZ":3579807591,"StartTime":0.0,"Objects":[{"StartTime":0.0,"EndTime":0.0,"Column":0}]},{"RandomW":273326509,"RandomX":671,"RandomY":842502087,"RandomZ":3579807591,"StartTime":125.0,"Objects":[{"StartTime":125.0,"EndTime":125.0,"Column":1}]},{"RandomW":273326509,"RandomX":671,"RandomY":842502087,"RandomZ":3579807591,"StartTime":250.0,"Objects":[{"StartTime":250.0,"EndTime":250.0,"Column":2}]},{"RandomW":273326509,"RandomX":671,"RandomY":842502087,"RandomZ":3579807591,"StartTime":375.0,"Objects":[{"StartTime":375.0,"EndTime":375.0,"Column":3}]},{"RandomW":273326509,"RandomX":671,"RandomY":842502087,"RandomZ":3579807591,"StartTime":500.0,"Objects":[{"StartTime":500.0,"EndTime":500.0,"Column":4}]},{"RandomW":273326509,"RandomX":671,"RandomY":842502087,"RandomZ":3579807591,"StartTime":625.0,"Objects":[{"StartTime":625.0,"EndTime":625.0,"Column":5}]},{"RandomW":273326509,"RandomX":671,"RandomY":842502087,"RandomZ":3579807591,"StartTime":750.0,"Objects":[{"StartTime":750.0,"EndTime":750.0,"Column":6}]},{"RandomW":273326509,"RandomX":671,"RandomY":842502087,"RandomZ":3579807591,"StartTime":875.0,"Objects":[{"StartTime":875.0,"EndTime":875.0,"Column":7}]},{"RandomW":273326509,"RandomX":671,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1000.0,"Objects":[{"StartTime":1000.0,"EndTime":1000.0,"Column":8}]},{"RandomW":273326509,"RandomX":671,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1125.0,"Objects":[{"StartTime":1125.0,"EndTime":1125.0,"Column":9}]},{"RandomW":273326509,"RandomX":671,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1250.0,"Objects":[{"StartTime":1250.0,"EndTime":1250.0,"Column":10}]},{"RandomW":273326509,"RandomX":671,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1375.0,"Objects":[{"StartTime":1375.0,"EndTime":1375.0,"Column":11}]},{"RandomW":273326509,"RandomX":671,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1500.0,"Objects":[{"StartTime":1500.0,"EndTime":1500.0,"Column":12}]},{"RandomW":273326509,"RandomX":671,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1625.0,"Objects":[{"StartTime":1625.0,"EndTime":1625.0,"Column":13}]},{"RandomW":273326509,"RandomX":671,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1750.0,"Objects":[{"StartTime":1750.0,"EndTime":1750.0,"Column":14}]},{"RandomW":273326509,"RandomX":671,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1875.0,"Objects":[{"StartTime":1875.0,"EndTime":1875.0,"Column":15}]},{"RandomW":273326509,"RandomX":671,"RandomY":842502087,"RandomZ":3579807591,"StartTime":2000.0,"Objects":[{"StartTime":2000.0,"EndTime":2000.0,"Column":16}]},{"RandomW":273326509,"RandomX":671,"RandomY":842502087,"RandomZ":3579807591,"StartTime":2125.0,"Objects":[{"StartTime":2125.0,"EndTime":2125.0,"Column":17}]}]}
@@ -0,0 +1,54 @@
osu file format v14
[General]
Mode: 3
[Metadata]
Title:keycount test
TitleUnicode:keycount test
Artist:mania
ArtistUnicode:mania
Creator:spaceman_atlas
Version:18K
[Difficulty]
HPDrainRate:5
CircleSize:18
OverallDifficulty:5
ApproachRate:5
SliderMultiplier:1.4
SliderTickRate:1
[Events]
//Background and Video events
//Break Periods
//Storyboard Layer 0 (Background)
//Storyboard Layer 1 (Fail)
//Storyboard Layer 2 (Pass)
//Storyboard Layer 3 (Foreground)
//Storyboard Layer 4 (Overlay)
//Storyboard Sound Samples
[TimingPoints]
0,500,4,2,0,100,1,0
[HitObjects]
14,192,0,1,0,0:0:0:0:
42,192,125,1,0,0:0:0:0:
71,192,250,1,0,0:0:0:0:
99,192,375,1,0,0:0:0:0:
128,192,500,1,0,0:0:0:0:
156,192,625,1,0,0:0:0:0:
184,192,750,1,0,0:0:0:0:
213,192,875,1,0,0:0:0:0:
241,192,1000,1,0,0:0:0:0:
270,192,1125,1,0,0:0:0:0:
298,192,1250,1,0,0:0:0:0:
327,192,1375,1,0,0:0:0:0:
355,192,1500,1,0,0:0:0:0:
384,192,1625,1,0,0:0:0:0:
412,192,1750,1,0,0:0:0:0:
440,192,1875,1,0,0:0:0:0:
469,192,2000,1,0,0:0:0:0:
497,192,2125,1,0,0:0:0:0:
@@ -0,0 +1 @@
{"Mappings":[{"RandomW":273326509,"RandomX":331,"RandomY":842502087,"RandomZ":3579807591,"StartTime":0.0,"Objects":[{"StartTime":0.0,"EndTime":0.0,"Column":0}]}]}
@@ -0,0 +1,37 @@
osu file format v14
[General]
Mode: 3
[Metadata]
Title:keycount test
TitleUnicode:keycount test
Artist:mania
ArtistUnicode:mania
Creator:spaceman_atlas
Version:1K
[Difficulty]
HPDrainRate:5
CircleSize:1
OverallDifficulty:5
ApproachRate:5
SliderMultiplier:1.4
SliderTickRate:1
[Events]
//Background and Video events
//Break Periods
//Storyboard Layer 0 (Background)
//Storyboard Layer 1 (Fail)
//Storyboard Layer 2 (Pass)
//Storyboard Layer 3 (Foreground)
//Storyboard Layer 4 (Overlay)
//Storyboard Sound Samples
[TimingPoints]
0,500,4,2,0,100,1,0
[HitObjects]
256,192,0,1,0,0:0:0:0:
@@ -0,0 +1 @@
{"Mappings":[{"RandomW":273326509,"RandomX":351,"RandomY":842502087,"RandomZ":3579807591,"StartTime":0.0,"Objects":[{"StartTime":0.0,"EndTime":0.0,"Column":0}]},{"RandomW":273326509,"RandomX":351,"RandomY":842502087,"RandomZ":3579807591,"StartTime":125.0,"Objects":[{"StartTime":125.0,"EndTime":125.0,"Column":1}]}]}
@@ -0,0 +1,38 @@
osu file format v14
[General]
Mode: 3
[Metadata]
Title:keycount test
TitleUnicode:keycount test
Artist:mania
ArtistUnicode:mania
Creator:spaceman_atlas
Version:2K
[Difficulty]
HPDrainRate:5
CircleSize:2
OverallDifficulty:5
ApproachRate:5
SliderMultiplier:1.4
SliderTickRate:1
[Events]
//Background and Video events
//Break Periods
//Storyboard Layer 0 (Background)
//Storyboard Layer 1 (Fail)
//Storyboard Layer 2 (Pass)
//Storyboard Layer 3 (Foreground)
//Storyboard Layer 4 (Overlay)
//Storyboard Sound Samples
[TimingPoints]
0,500,4,2,0,100,1,0
[HitObjects]
128,192,0,1,0,0:0:0:0:
384,192,125,1,0,0:0:0:0:
@@ -0,0 +1 @@
{"Mappings":[{"RandomW":273326509,"RandomX":371,"RandomY":842502087,"RandomZ":3579807591,"StartTime":0.0,"Objects":[{"StartTime":0.0,"EndTime":0.0,"Column":0}]},{"RandomW":273326509,"RandomX":371,"RandomY":842502087,"RandomZ":3579807591,"StartTime":125.0,"Objects":[{"StartTime":125.0,"EndTime":125.0,"Column":1}]},{"RandomW":273326509,"RandomX":371,"RandomY":842502087,"RandomZ":3579807591,"StartTime":250.0,"Objects":[{"StartTime":250.0,"EndTime":250.0,"Column":2}]}]}
@@ -0,0 +1,39 @@
osu file format v14
[General]
Mode: 3
[Metadata]
Title:keycount test
TitleUnicode:keycount test
Artist:mania
ArtistUnicode:mania
Creator:spaceman_atlas
Version:3K
[Difficulty]
HPDrainRate:5
CircleSize:3
OverallDifficulty:5
ApproachRate:5
SliderMultiplier:1.4
SliderTickRate:1
[Events]
//Background and Video events
//Break Periods
//Storyboard Layer 0 (Background)
//Storyboard Layer 1 (Fail)
//Storyboard Layer 2 (Pass)
//Storyboard Layer 3 (Foreground)
//Storyboard Layer 4 (Overlay)
//Storyboard Sound Samples
[TimingPoints]
0,500,4,2,0,100,1,0
[HitObjects]
85,192,0,1,0,0:0:0:0:
256,192,125,1,0,0:0:0:0:
426,192,250,1,0,0:0:0:0:
@@ -0,0 +1 @@
{"Mappings":[{"RandomW":273326509,"RandomX":391,"RandomY":842502087,"RandomZ":3579807591,"StartTime":0.0,"Objects":[{"StartTime":0.0,"EndTime":0.0,"Column":0}]},{"RandomW":273326509,"RandomX":391,"RandomY":842502087,"RandomZ":3579807591,"StartTime":125.0,"Objects":[{"StartTime":125.0,"EndTime":125.0,"Column":1}]},{"RandomW":273326509,"RandomX":391,"RandomY":842502087,"RandomZ":3579807591,"StartTime":250.0,"Objects":[{"StartTime":250.0,"EndTime":250.0,"Column":2}]},{"RandomW":273326509,"RandomX":391,"RandomY":842502087,"RandomZ":3579807591,"StartTime":375.0,"Objects":[{"StartTime":375.0,"EndTime":375.0,"Column":3}]}]}
@@ -0,0 +1,40 @@
osu file format v14
[General]
Mode: 3
[Metadata]
Title:keycount test
TitleUnicode:keycount test
Artist:mania
ArtistUnicode:mania
Creator:spaceman_atlas
Version:4K
[Difficulty]
HPDrainRate:5
CircleSize:4
OverallDifficulty:5
ApproachRate:5
SliderMultiplier:1.4
SliderTickRate:1
[Events]
//Background and Video events
//Break Periods
//Storyboard Layer 0 (Background)
//Storyboard Layer 1 (Fail)
//Storyboard Layer 2 (Pass)
//Storyboard Layer 3 (Foreground)
//Storyboard Layer 4 (Overlay)
//Storyboard Sound Samples
[TimingPoints]
0,500,4,2,0,100,1,0
[HitObjects]
64,192,0,1,0,0:0:0:0:
192,192,125,1,0,0:0:0:0:
320,192,250,1,0,0:0:0:0:
448,192,375,1,0,0:0:0:0:
@@ -0,0 +1 @@
{"Mappings":[{"RandomW":273326509,"RandomX":411,"RandomY":842502087,"RandomZ":3579807591,"StartTime":0.0,"Objects":[{"StartTime":0.0,"EndTime":0.0,"Column":0}]},{"RandomW":273326509,"RandomX":411,"RandomY":842502087,"RandomZ":3579807591,"StartTime":125.0,"Objects":[{"StartTime":125.0,"EndTime":125.0,"Column":1}]},{"RandomW":273326509,"RandomX":411,"RandomY":842502087,"RandomZ":3579807591,"StartTime":250.0,"Objects":[{"StartTime":250.0,"EndTime":250.0,"Column":2}]},{"RandomW":273326509,"RandomX":411,"RandomY":842502087,"RandomZ":3579807591,"StartTime":375.0,"Objects":[{"StartTime":375.0,"EndTime":375.0,"Column":3}]},{"RandomW":273326509,"RandomX":411,"RandomY":842502087,"RandomZ":3579807591,"StartTime":500.0,"Objects":[{"StartTime":500.0,"EndTime":500.0,"Column":4}]}]}
@@ -0,0 +1,41 @@
osu file format v14
[General]
Mode: 3
[Metadata]
Title:keycount test
TitleUnicode:keycount test
Artist:mania
ArtistUnicode:mania
Creator:spaceman_atlas
Version:5K
[Difficulty]
HPDrainRate:5
CircleSize:5
OverallDifficulty:5
ApproachRate:5
SliderMultiplier:1.4
SliderTickRate:1
[Events]
//Background and Video events
//Break Periods
//Storyboard Layer 0 (Background)
//Storyboard Layer 1 (Fail)
//Storyboard Layer 2 (Pass)
//Storyboard Layer 3 (Foreground)
//Storyboard Layer 4 (Overlay)
//Storyboard Sound Samples
[TimingPoints]
0,500,4,2,0,100,1,0
[HitObjects]
51,192,0,1,0,0:0:0:0:
153,192,125,1,0,0:0:0:0:
256,192,250,1,0,0:0:0:0:
358,192,375,1,0,0:0:0:0:
460,192,500,1,0,0:0:0:0:
@@ -0,0 +1 @@
{"Mappings":[{"RandomW":273326509,"RandomX":431,"RandomY":842502087,"RandomZ":3579807591,"StartTime":0.0,"Objects":[{"StartTime":0.0,"EndTime":0.0,"Column":0}]},{"RandomW":273326509,"RandomX":431,"RandomY":842502087,"RandomZ":3579807591,"StartTime":125.0,"Objects":[{"StartTime":125.0,"EndTime":125.0,"Column":1}]},{"RandomW":273326509,"RandomX":431,"RandomY":842502087,"RandomZ":3579807591,"StartTime":250.0,"Objects":[{"StartTime":250.0,"EndTime":250.0,"Column":2}]},{"RandomW":273326509,"RandomX":431,"RandomY":842502087,"RandomZ":3579807591,"StartTime":375.0,"Objects":[{"StartTime":375.0,"EndTime":375.0,"Column":3}]},{"RandomW":273326509,"RandomX":431,"RandomY":842502087,"RandomZ":3579807591,"StartTime":500.0,"Objects":[{"StartTime":500.0,"EndTime":500.0,"Column":4}]},{"RandomW":273326509,"RandomX":431,"RandomY":842502087,"RandomZ":3579807591,"StartTime":625.0,"Objects":[{"StartTime":625.0,"EndTime":625.0,"Column":5}]}]}
@@ -0,0 +1,42 @@
osu file format v14
[General]
Mode: 3
[Metadata]
Title:keycount test
TitleUnicode:keycount test
Artist:mania
ArtistUnicode:mania
Creator:spaceman_atlas
Version:6K
[Difficulty]
HPDrainRate:5
CircleSize:6
OverallDifficulty:5
ApproachRate:5
SliderMultiplier:1.4
SliderTickRate:1
[Events]
//Background and Video events
//Break Periods
//Storyboard Layer 0 (Background)
//Storyboard Layer 1 (Fail)
//Storyboard Layer 2 (Pass)
//Storyboard Layer 3 (Foreground)
//Storyboard Layer 4 (Overlay)
//Storyboard Sound Samples
[TimingPoints]
0,500,4,2,0,100,1,0
[HitObjects]
42,192,0,1,0,0:0:0:0:
128,192,125,1,0,0:0:0:0:
213,192,250,1,0,0:0:0:0:
298,192,375,1,0,0:0:0:0:
384,192,500,1,0,0:0:0:0:
469,192,625,1,0,0:0:0:0:
@@ -0,0 +1,45 @@
osu file format v14
[General]
Mode: 3
SpecialStyle:1
[Metadata]
Title:keycount test
TitleUnicode:keycount test
Artist:mania
ArtistUnicode:mania
Creator:spaceman_atlas
Version:8K
[Difficulty]
HPDrainRate:5
CircleSize:8
OverallDifficulty:5
ApproachRate:5
SliderMultiplier:1.4
SliderTickRate:1
[Events]
//Background and Video events
//Break Periods
//Storyboard Layer 0 (Background)
//Storyboard Layer 1 (Fail)
//Storyboard Layer 2 (Pass)
//Storyboard Layer 3 (Foreground)
//Storyboard Layer 4 (Overlay)
//Storyboard Sound Samples
[TimingPoints]
0,500,4,2,0,100,1,0
[HitObjects]
32,192,0,1,0,0:0:0:0:
96,192,125,1,0,0:0:0:0:
160,192,250,1,0,0:0:0:0:
224,192,375,1,0,0:0:0:0:
288,192,500,1,0,0:0:0:0:
352,192,625,1,0,0:0:0:0:
416,192,750,1,0,0:0:0:0:
480,192,875,1,0,0:0:0:0:
@@ -0,0 +1 @@
{"Mappings":[{"RandomW":273326509,"RandomX":451,"RandomY":842502087,"RandomZ":3579807591,"StartTime":0.0,"Objects":[{"StartTime":0.0,"EndTime":0.0,"Column":0}]},{"RandomW":273326509,"RandomX":451,"RandomY":842502087,"RandomZ":3579807591,"StartTime":125.0,"Objects":[{"StartTime":125.0,"EndTime":125.0,"Column":1}]},{"RandomW":273326509,"RandomX":451,"RandomY":842502087,"RandomZ":3579807591,"StartTime":250.0,"Objects":[{"StartTime":250.0,"EndTime":250.0,"Column":2}]},{"RandomW":273326509,"RandomX":451,"RandomY":842502087,"RandomZ":3579807591,"StartTime":375.0,"Objects":[{"StartTime":375.0,"EndTime":375.0,"Column":3}]},{"RandomW":273326509,"RandomX":451,"RandomY":842502087,"RandomZ":3579807591,"StartTime":500.0,"Objects":[{"StartTime":500.0,"EndTime":500.0,"Column":4}]},{"RandomW":273326509,"RandomX":451,"RandomY":842502087,"RandomZ":3579807591,"StartTime":625.0,"Objects":[{"StartTime":625.0,"EndTime":625.0,"Column":5}]},{"RandomW":273326509,"RandomX":451,"RandomY":842502087,"RandomZ":3579807591,"StartTime":750.0,"Objects":[{"StartTime":750.0,"EndTime":750.0,"Column":6}]}]}
@@ -0,0 +1,43 @@
osu file format v14
[General]
Mode: 3
[Metadata]
Title:keycount test
TitleUnicode:keycount test
Artist:mania
ArtistUnicode:mania
Creator:spaceman_atlas
Version:7K
[Difficulty]
HPDrainRate:5
CircleSize:7
OverallDifficulty:5
ApproachRate:5
SliderMultiplier:1.4
SliderTickRate:1
[Events]
//Background and Video events
//Break Periods
//Storyboard Layer 0 (Background)
//Storyboard Layer 1 (Fail)
//Storyboard Layer 2 (Pass)
//Storyboard Layer 3 (Foreground)
//Storyboard Layer 4 (Overlay)
//Storyboard Sound Samples
[TimingPoints]
0,500,4,2,0,100,1,0
[HitObjects]
36,192,0,1,0,0:0:0:0:
109,192,125,1,0,0:0:0:0:
182,192,250,1,0,0:0:0:0:
256,192,375,1,0,0:0:0:0:
329,192,500,1,0,0:0:0:0:
402,192,625,1,0,0:0:0:0:
475,192,750,1,0,0:0:0:0:
@@ -0,0 +1 @@
{"Mappings":[{"RandomW":273326509,"RandomX":471,"RandomY":842502087,"RandomZ":3579807591,"StartTime":0.0,"Objects":[{"StartTime":0.0,"EndTime":0.0,"Column":0}]},{"RandomW":273326509,"RandomX":471,"RandomY":842502087,"RandomZ":3579807591,"StartTime":125.0,"Objects":[{"StartTime":125.0,"EndTime":125.0,"Column":1}]},{"RandomW":273326509,"RandomX":471,"RandomY":842502087,"RandomZ":3579807591,"StartTime":250.0,"Objects":[{"StartTime":250.0,"EndTime":250.0,"Column":2}]},{"RandomW":273326509,"RandomX":471,"RandomY":842502087,"RandomZ":3579807591,"StartTime":375.0,"Objects":[{"StartTime":375.0,"EndTime":375.0,"Column":3}]},{"RandomW":273326509,"RandomX":471,"RandomY":842502087,"RandomZ":3579807591,"StartTime":500.0,"Objects":[{"StartTime":500.0,"EndTime":500.0,"Column":4}]},{"RandomW":273326509,"RandomX":471,"RandomY":842502087,"RandomZ":3579807591,"StartTime":625.0,"Objects":[{"StartTime":625.0,"EndTime":625.0,"Column":5}]},{"RandomW":273326509,"RandomX":471,"RandomY":842502087,"RandomZ":3579807591,"StartTime":750.0,"Objects":[{"StartTime":750.0,"EndTime":750.0,"Column":6}]},{"RandomW":273326509,"RandomX":471,"RandomY":842502087,"RandomZ":3579807591,"StartTime":875.0,"Objects":[{"StartTime":875.0,"EndTime":875.0,"Column":7}]}]}
@@ -0,0 +1,44 @@
osu file format v14
[General]
Mode: 3
[Metadata]
Title:keycount test
TitleUnicode:keycount test
Artist:mania
ArtistUnicode:mania
Creator:spaceman_atlas
Version:8K
[Difficulty]
HPDrainRate:5
CircleSize:8
OverallDifficulty:5
ApproachRate:5
SliderMultiplier:1.4
SliderTickRate:1
[Events]
//Background and Video events
//Break Periods
//Storyboard Layer 0 (Background)
//Storyboard Layer 1 (Fail)
//Storyboard Layer 2 (Pass)
//Storyboard Layer 3 (Foreground)
//Storyboard Layer 4 (Overlay)
//Storyboard Sound Samples
[TimingPoints]
0,500,4,2,0,100,1,0
[HitObjects]
32,192,0,1,0,0:0:0:0:
96,192,125,1,0,0:0:0:0:
160,192,250,1,0,0:0:0:0:
224,192,375,1,0,0:0:0:0:
288,192,500,1,0,0:0:0:0:
352,192,625,1,0,0:0:0:0:
416,192,750,1,0,0:0:0:0:
480,192,875,1,0,0:0:0:0:
@@ -0,0 +1 @@
{"Mappings":[{"RandomW":273326509,"RandomX":491,"RandomY":842502087,"RandomZ":3579807591,"StartTime":0.0,"Objects":[{"StartTime":0.0,"EndTime":0.0,"Column":0}]},{"RandomW":273326509,"RandomX":491,"RandomY":842502087,"RandomZ":3579807591,"StartTime":125.0,"Objects":[{"StartTime":125.0,"EndTime":125.0,"Column":1}]},{"RandomW":273326509,"RandomX":491,"RandomY":842502087,"RandomZ":3579807591,"StartTime":250.0,"Objects":[{"StartTime":250.0,"EndTime":250.0,"Column":2}]},{"RandomW":273326509,"RandomX":491,"RandomY":842502087,"RandomZ":3579807591,"StartTime":375.0,"Objects":[{"StartTime":375.0,"EndTime":375.0,"Column":3}]},{"RandomW":273326509,"RandomX":491,"RandomY":842502087,"RandomZ":3579807591,"StartTime":500.0,"Objects":[{"StartTime":500.0,"EndTime":500.0,"Column":4}]},{"RandomW":273326509,"RandomX":491,"RandomY":842502087,"RandomZ":3579807591,"StartTime":625.0,"Objects":[{"StartTime":625.0,"EndTime":625.0,"Column":5}]},{"RandomW":273326509,"RandomX":491,"RandomY":842502087,"RandomZ":3579807591,"StartTime":750.0,"Objects":[{"StartTime":750.0,"EndTime":750.0,"Column":6}]},{"RandomW":273326509,"RandomX":491,"RandomY":842502087,"RandomZ":3579807591,"StartTime":875.0,"Objects":[{"StartTime":875.0,"EndTime":875.0,"Column":7}]},{"RandomW":273326509,"RandomX":491,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1000.0,"Objects":[{"StartTime":1000.0,"EndTime":1000.0,"Column":8}]}]}
@@ -0,0 +1,45 @@
osu file format v14
[General]
Mode: 3
[Metadata]
Title:keycount test
TitleUnicode:keycount test
Artist:mania
ArtistUnicode:mania
Creator:spaceman_atlas
Version:9K
[Difficulty]
HPDrainRate:5
CircleSize:9
OverallDifficulty:5
ApproachRate:5
SliderMultiplier:1.4
SliderTickRate:1
[Events]
//Background and Video events
//Break Periods
//Storyboard Layer 0 (Background)
//Storyboard Layer 1 (Fail)
//Storyboard Layer 2 (Pass)
//Storyboard Layer 3 (Foreground)
//Storyboard Layer 4 (Overlay)
//Storyboard Sound Samples
[TimingPoints]
0,500,4,2,0,100,1,0
[HitObjects]
28,192,0,1,0,0:0:0:0:
85,192,125,1,0,0:0:0:0:
142,192,250,1,0,0:0:0:0:
199,192,375,1,0,0:0:0:0:
256,192,500,1,0,0:0:0:0:
312,192,625,1,0,0:0:0:0:
369,192,750,1,0,0:0:0:0:
426,192,875,1,0,0:0:0:0:
483,192,1000,1,0,0:0:0:0:
@@ -33,6 +33,8 @@ namespace osu.Game.Rulesets.Mania.Tests
/// </summary>
public partial class TestSceneHoldNoteInput : RateAdjustedBeatmapTestScene
{
protected override Ruleset CreateRuleset() => new ManiaRuleset();
private const double time_before_head = 250;
private const double time_head = 1500;
private const double time_during_hold_1 = 2500;
@@ -21,6 +21,8 @@ namespace osu.Game.Rulesets.Mania.Tests
{
public partial class TestSceneMaximumScore : RateAdjustedBeatmapTestScene
{
protected override Ruleset CreateRuleset() => new ManiaRuleset();
private ScoreAccessibleReplayPlayer currentPlayer = null!;
private List<JudgementResult> judgementResults = new List<JudgementResult>();
@@ -26,6 +26,8 @@ namespace osu.Game.Rulesets.Mania.Tests
{
public partial class TestSceneOutOfOrderHits : RateAdjustedBeatmapTestScene
{
protected override Ruleset CreateRuleset() => new ManiaRuleset();
[Test]
public void TestPreviousHitWindowDoesNotExtendPastNextObject()
{
@@ -20,6 +20,8 @@ namespace osu.Game.Rulesets.Mania.Tests
{
public partial class TestSceneReplayRewinding : RateAdjustedBeatmapTestScene
{
protected override Ruleset CreateRuleset() => new ManiaRuleset();
private ReplayPlayer currentPlayer = null!;
[Test]
@@ -26,6 +26,8 @@ namespace osu.Game.Rulesets.Mania.Tests
[TestFixture]
public partial class TestSceneTimingBasedNoteColouring : OsuTestScene
{
protected override Ruleset CreateRuleset() => new ManiaRuleset();
private Bindable<bool> configTimingBasedNoteColouring;
private ManualClock clock;
@@ -11,5 +11,6 @@
</PropertyGroup>
<ItemGroup Label="Project References">
<ProjectReference Include="..\osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj" />
<ProjectReference Include="..\osu.Game.Tests\osu.Game.Tests.csproj" />
</ItemGroup>
</Project>
@@ -66,6 +66,8 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
if (IsForCurrentRuleset && TargetColumns > ManiaRuleset.MAX_STAGE_KEYS)
{
// If support for odd key counts above 10 (11 / 13 / 15 / 17K) is ever desired, this code needs to go.
// For now, it's probably fine, as stable doesn't support them outside of manual .osu edits either.
TargetColumns /= 2;
Dual = true;
}
@@ -98,9 +98,9 @@ namespace osu.Game.Rulesets.Mania
return false;
}
public bool FilterMayChangeFromMods(ValueChangedEvent<IReadOnlyList<Mod>> mods)
public bool FilterMayChangeFromMods(FilterCriteria criteria, ValueChangedEvent<IReadOnlyList<Mod>> mods)
{
if (includedKeyCounts.Count != LegacyBeatmapDecoder.MAX_MANIA_KEY_COUNT)
if (includedKeyCounts.Count != LegacyBeatmapDecoder.MAX_MANIA_KEY_COUNT || criteria.Group == GroupMode.Variant)
{
// Interpreting as the Mod type is required for equality comparison.
HashSet<Mod> oldSet = mods.OldValue.OfType<ManiaKeyMod>().AsEnumerable<Mod>().ToHashSet();
+5
View File
@@ -327,6 +327,8 @@ namespace osu.Game.Rulesets.Mania
public override RulesetSettingsSubsection CreateSettings() => new ManiaSettingsSubsection(this);
public override LocalisableString VariantDescription => "Keys";
public override IEnumerable<int> AvailableVariants
{
get
@@ -498,6 +500,9 @@ namespace osu.Game.Rulesets.Mania
public int GetKeyCount(IBeatmapInfo beatmapInfo, IReadOnlyList<Mod>? mods = null)
=> ManiaBeatmapConverter.GetColumnCount(LegacyBeatmapConversionDifficultyInfo.FromBeatmapInfo(beatmapInfo), mods);
public override int GetVariantForBeatmap(IBeatmapInfo beatmapInfo, IReadOnlyList<Mod>? mods = null)
=> GetKeyCount(beatmapInfo, mods);
}
public enum PlayfieldType
@@ -1,7 +1,6 @@
// 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 osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Game.Graphics;
@@ -57,11 +56,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
if (lastVersion != hitObject.Path.Version.Value)
{
lastVersion = hitObject.Path.Version.Value;
var vertices = new List<Vector2>();
hitObject.Path.GetPathToProgress(vertices, 0, 1);
body.SetVertices(vertices);
body.SetVertices(hitObject.Path.CalculatedPath);
}
OriginPosition = body.PathOffset;
@@ -3,6 +3,7 @@
using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites;
using osu.Game.Graphics;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Edit.Tools;
using osu.Game.Rulesets.Osu.Edit.Blueprints;
@@ -22,7 +23,7 @@ namespace osu.Game.Rulesets.Osu.Edit
""";
}
public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.Solid.DraftingCompass };
public override Drawable CreateIcon() => new SpriteIcon { Icon = OsuIcon.EditorGrid };
public override PlacementBlueprint CreatePlacementBlueprint() => new GridPlacementBlueprint();
}
@@ -2,7 +2,8 @@
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Graphics;
using osu.Game.Beatmaps;
using osu.Framework.Graphics.Sprites;
using osu.Game.Graphics;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Edit.Tools;
using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles;
@@ -17,7 +18,7 @@ namespace osu.Game.Rulesets.Osu.Edit
{
}
public override Drawable CreateIcon() => new BeatmapStatisticIcon(BeatmapStatisticsIconType.Circles);
public override Drawable CreateIcon() => new SpriteIcon { Icon = OsuIcon.EditorHitCircle };
public override HitObjectPlacementBlueprint CreatePlacementBlueprint() => new HitCirclePlacementBlueprint();
}
@@ -2,7 +2,8 @@
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Graphics;
using osu.Game.Beatmaps;
using osu.Framework.Graphics.Sprites;
using osu.Game.Graphics;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Edit.Tools;
using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders;
@@ -24,7 +25,7 @@ namespace osu.Game.Rulesets.Osu.Edit
""";
}
public override Drawable CreateIcon() => new BeatmapStatisticIcon(BeatmapStatisticsIconType.Sliders);
public override Drawable CreateIcon() => new SpriteIcon { Icon = OsuIcon.EditorSlider };
public override HitObjectPlacementBlueprint CreatePlacementBlueprint() => new SliderPlacementBlueprint();
}
@@ -2,7 +2,8 @@
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Graphics;
using osu.Game.Beatmaps;
using osu.Framework.Graphics.Sprites;
using osu.Game.Graphics;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Edit.Tools;
using osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners;
@@ -17,7 +18,7 @@ namespace osu.Game.Rulesets.Osu.Edit
{
}
public override Drawable CreateIcon() => new BeatmapStatisticIcon(BeatmapStatisticsIconType.Spinners);
public override Drawable CreateIcon() => new SpriteIcon { Icon = OsuIcon.EditorSpinner };
public override HitObjectPlacementBlueprint CreatePlacementBlueprint() => new SpinnerPlacementBlueprint();
}
@@ -9,12 +9,12 @@ namespace osu.Game.Rulesets.Osu.Skinning.Default
public partial class TrianglesPiece : Triangles
{
protected override bool CreateNewTriangles => false;
protected override float SpawnRatio => 0.5f;
public TrianglesPiece(int? seed = null)
: base(seed)
{
TriangleScale = 1.2f;
SpawnRatio = 0.5f;
HideAlphaDiscrepancies = false;
ClampAxes = Axes.None;
}
@@ -105,7 +105,8 @@ namespace osu.Game.Rulesets.Osu.Skinning
return;
// Generate the entire curve
drawableSlider.HitObject.Path.GetPathToProgress(CurrentCurve, 0, 1);
CurrentCurve.Clear();
CurrentCurve.AddRange(drawableSlider.HitObject.Path.CalculatedPath);
SetVertices(CurrentCurve);
// Force the body to be the final path size to avoid excessive autosize computations
@@ -265,9 +265,6 @@ namespace osu.Game.Rulesets.Osu.Utils
/// </remarks>
public static RectangleF CalculatePossibleMovementBounds(Slider slider)
{
var pathPositions = new List<Vector2>();
slider.Path.GetPathToProgress(pathPositions, 0, 1);
float minX = float.PositiveInfinity;
float maxX = float.NegativeInfinity;
@@ -275,7 +272,7 @@ namespace osu.Game.Rulesets.Osu.Utils
float maxY = float.NegativeInfinity;
// Compute the bounding box of the slider.
foreach (var pos in pathPositions)
foreach (var pos in slider.Path.CalculatedPath)
{
minX = MathF.Min(minX, pos.X);
maxX = MathF.Max(maxX, pos.X);
@@ -46,11 +46,11 @@ namespace osu.Game.Tests.Beatmaps.Formats
{
const string name = "Resources/storyboard_only_video.osu";
var decoded = decodeFromLegacy(beatmaps_resource_store.GetStream(name), name);
var decoded = DecodeFromLegacy(beatmaps_resource_store.GetStream(name), beatmaps_resource_store, name);
Assert.That(decoded.beatmap.UnhandledEventLines.Count, Is.EqualTo(1));
Assert.That(decoded.beatmap.UnhandledEventLines.Single(), Is.EqualTo("Video,0,\"video.avi\""));
var memoryStream = encodeToLegacy(decoded);
var memoryStream = EncodeToLegacy(decoded);
var storyboard = new LegacyStoryboardDecoder().Decode(new LineBufferedReader(memoryStream));
StoryboardLayer video = storyboard.Layers.Single(l => l.Name == "Video");
@@ -60,42 +60,42 @@ namespace osu.Game.Tests.Beatmaps.Formats
[TestCaseSource(nameof(allBeatmaps))]
public void TestEncodeDecodeStability(string name)
{
var decoded = decodeFromLegacy(beatmaps_resource_store.GetStream(name), name);
var decodedAfterEncode = decodeFromLegacy(encodeToLegacy(decoded), name);
var decoded = DecodeFromLegacy(beatmaps_resource_store.GetStream(name), beatmaps_resource_store, name);
var decodedAfterEncode = DecodeFromLegacy(EncodeToLegacy(decoded), beatmaps_resource_store, name);
sort(decoded.beatmap);
sort(decodedAfterEncode.beatmap);
Sort(decoded.beatmap);
Sort(decodedAfterEncode.beatmap);
compareBeatmaps(decoded, decodedAfterEncode);
CompareBeatmaps(decoded, decodedAfterEncode);
}
[TestCaseSource(nameof(allBeatmaps))]
public void TestEncodeDecodeStabilityDoubleConvert(string name)
{
var decoded = decodeFromLegacy(beatmaps_resource_store.GetStream(name), name);
var decodedAfterEncode = decodeFromLegacy(encodeToLegacy(decoded), name);
var decoded = DecodeFromLegacy(beatmaps_resource_store.GetStream(name), beatmaps_resource_store, name);
var decodedAfterEncode = DecodeFromLegacy(EncodeToLegacy(decoded), beatmaps_resource_store, name);
// run an extra convert. this is expected to be stable.
decodedAfterEncode.beatmap = convert(decodedAfterEncode.beatmap);
sort(decoded.beatmap);
sort(decodedAfterEncode.beatmap);
Sort(decoded.beatmap);
Sort(decodedAfterEncode.beatmap);
compareBeatmaps(decoded, decodedAfterEncode);
CompareBeatmaps(decoded, decodedAfterEncode);
}
[TestCaseSource(nameof(allBeatmaps))]
public void TestEncodeDecodeStabilityWithNonLegacyControlPoints(string name)
{
var decoded = decodeFromLegacy(beatmaps_resource_store.GetStream(name), name);
var decoded = DecodeFromLegacy(beatmaps_resource_store.GetStream(name), beatmaps_resource_store, name);
// we are testing that the transfer of relevant data to hitobjects (from legacy control points) sticks through encode/decode.
// before the encode step, the legacy information is removed here.
decoded.beatmap.ControlPointInfo = removeLegacyControlPointTypes(decoded.beatmap.ControlPointInfo);
var decodedAfterEncode = decodeFromLegacy(encodeToLegacy(decoded), name);
var decodedAfterEncode = DecodeFromLegacy(EncodeToLegacy(decoded), beatmaps_resource_store, name);
compareBeatmaps(decoded, decodedAfterEncode);
CompareBeatmaps(decoded, decodedAfterEncode);
static ControlPointInfo removeLegacyControlPointTypes(ControlPointInfo controlPointInfo)
{
@@ -120,7 +120,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
}
}
private void compareBeatmaps((IBeatmap beatmap, TestLegacySkin skin) expected, (IBeatmap beatmap, TestLegacySkin skin) actual)
public static void CompareBeatmaps((IBeatmap beatmap, TestLegacySkin skin) expected, (IBeatmap beatmap, TestLegacySkin skin) actual)
{
// Check all control points that are still considered to be at a global level.
Assert.That(actual.beatmap.ControlPointInfo.TimingPoints.Serialize(), Is.EqualTo(expected.beatmap.ControlPointInfo.TimingPoints.Serialize()));
@@ -153,7 +153,8 @@ namespace osu.Game.Tests.Beatmaps.Formats
}
};
var decodedAfterEncode = decodeFromLegacy(encodeToLegacy((beatmap, new TestLegacySkin(beatmaps_resource_store, string.Empty))), string.Empty);
var encoded = EncodeToLegacy((beatmap, new TestLegacySkin(beatmaps_resource_store, string.Empty)));
var decodedAfterEncode = DecodeFromLegacy(encoded, beatmaps_resource_store, string.Empty);
var decodedSlider = (Slider)decodedAfterEncode.beatmap.HitObjects[0];
Assert.That(decodedSlider.Path.ControlPoints.Count, Is.EqualTo(4));
Assert.That(decodedSlider.Path.ControlPoints[0].Type, Is.EqualTo(PathType.BSpline(3)));
@@ -182,7 +183,8 @@ namespace osu.Game.Tests.Beatmaps.Formats
}
};
var decodedAfterEncode = decodeFromLegacy(encodeToLegacy((beatmap, new TestLegacySkin(beatmaps_resource_store, string.Empty))), string.Empty);
var encoded = EncodeToLegacy((beatmap, new TestLegacySkin(beatmaps_resource_store, string.Empty)));
var decodedAfterEncode = DecodeFromLegacy(encoded, beatmaps_resource_store, string.Empty);
var decodedSlider = (Slider)decodedAfterEncode.beatmap.HitObjects[0];
Assert.That(decodedSlider.Path.ControlPoints.Count, Is.EqualTo(5));
}
@@ -209,7 +211,8 @@ namespace osu.Game.Tests.Beatmaps.Formats
}
};
var decodedAfterEncode = decodeFromLegacy(encodeToLegacy((new Beatmap(), beatmapSkin)), string.Empty);
var encoded = EncodeToLegacy((new Beatmap(), beatmapSkin));
var decodedAfterEncode = DecodeFromLegacy(encoded, beatmaps_resource_store, string.Empty);
Assert.That(decodedAfterEncode.skin.Configuration.CustomComboColours, Has.Count.EqualTo(8));
}
@@ -231,8 +234,8 @@ namespace osu.Game.Tests.Beatmaps.Formats
HitObjects = { originalSlider }
};
var encoded = encodeToLegacy((beatmap, new TestLegacySkin(beatmaps_resource_store, string.Empty)));
var decodedAfterEncode = decodeFromLegacy(encoded, string.Empty, version: LegacyBeatmapEncoder.FIRST_LAZER_VERSION);
var encoded = EncodeToLegacy((beatmap, new TestLegacySkin(beatmaps_resource_store, string.Empty)));
var decodedAfterEncode = DecodeFromLegacy(encoded, beatmaps_resource_store, string.Empty, version: LegacyBeatmapEncoder.FIRST_LAZER_VERSION);
var decodedSlider = (Slider)decodedAfterEncode.beatmap.HitObjects[0];
Assert.That(decodedSlider.Path.ControlPoints.Select(p => p.Position),
Is.EquivalentTo(originalSlider.Path.ControlPoints.Select(p => p.Position)));
@@ -251,7 +254,8 @@ namespace osu.Game.Tests.Beatmaps.Formats
}
};
var decodedAfterEncode = decodeFromLegacy(encodeToLegacy((beatmap, new TestLegacySkin(beatmaps_resource_store, string.Empty))), string.Empty);
var encoded = EncodeToLegacy((beatmap, new TestLegacySkin(beatmaps_resource_store, string.Empty)));
var decodedAfterEncode = DecodeFromLegacy(encoded, beatmaps_resource_store, string.Empty);
Assert.That(decodedAfterEncode.beatmap.HitObjects[0].Samples[0].Suffix, Is.Null);
Assert.That(decodedAfterEncode.beatmap.HitObjects[0].Samples[0].UseBeatmapSamples, Is.False);
@@ -263,7 +267,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
Assert.That(decodedAfterEncode.beatmap.HitObjects[2].Samples[0].UseBeatmapSamples, Is.True);
}
private bool areComboColoursEqual(IHasComboColours a, IHasComboColours b)
private static bool areComboColoursEqual(IHasComboColours a, IHasComboColours b)
{
// equal to null, no need to SequenceEqual
if (a.ComboColours == null && b.ComboColours == null)
@@ -275,7 +279,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
return a.ComboColours.SequenceEqual(b.ComboColours);
}
private void sort(IBeatmap beatmap)
public static void Sort(IBeatmap beatmap)
{
// Sort control points to ensure a sane ordering, as they may be parsed in different orders. This works because each group contains only uniquely-typed control points.
foreach (var g in beatmap.ControlPointInfo.Groups)
@@ -285,19 +289,19 @@ namespace osu.Game.Tests.Beatmaps.Formats
}
}
private (IBeatmap beatmap, TestLegacySkin skin) decodeFromLegacy(Stream stream, string name, int version = LegacyDecoder<Beatmap>.LATEST_VERSION)
public static (IBeatmap beatmap, TestLegacySkin skin) DecodeFromLegacy(Stream stream, IResourceStore<byte[]> beatmapsResourceStore, string name, int version = LegacyDecoder<Beatmap>.LATEST_VERSION)
{
using (var reader = new LineBufferedReader(stream))
{
var beatmap = new LegacyBeatmapDecoder(version) { ApplyOffsets = false }.Decode(reader);
var beatmapSkin = new TestLegacySkin(beatmaps_resource_store, name);
var beatmapSkin = new TestLegacySkin(beatmapsResourceStore, name);
stream.Seek(0, SeekOrigin.Begin);
beatmapSkin.Configuration = new LegacySkinDecoder().Decode(reader);
return (convert(beatmap), beatmapSkin);
}
}
private class TestLegacySkin : LegacySkin
public class TestLegacySkin : LegacySkin
{
public TestLegacySkin(IResourceStore<byte[]> fallbackStore, string fileName)
: base(new SkinInfo { Name = "Test Skin", Creator = "Craftplacer" }, null, fallbackStore, fileName)
@@ -305,7 +309,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
}
}
private MemoryStream encodeToLegacy((IBeatmap beatmap, ISkin skin) fullBeatmap)
public static MemoryStream EncodeToLegacy((IBeatmap beatmap, ISkin skin) fullBeatmap)
{
var (beatmap, beatmapSkin) = fullBeatmap;
var stream = new MemoryStream();
@@ -318,7 +322,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
return stream;
}
private IBeatmap convert(IBeatmap beatmap)
private static IBeatmap convert(IBeatmap beatmap)
{
switch (beatmap.BeatmapInfo.Ruleset.OnlineID)
{
+61
View File
@@ -0,0 +1,61 @@
// 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;
using System.Net.WebSockets;
using System.Threading;
using System.Threading.Tasks;
using osu.Game.IPC;
namespace osu.Game.Tests.IPC
{
public sealed class WebSocketClient : IDisposable
{
public event Action<string>? MessageReceived;
public event Action? Closed;
private readonly int port;
private WebSocketChannel? channel;
public WebSocketClient(int port)
{
this.port = port;
}
public async Task Start(CancellationToken cancellationToken = default)
{
var webSocket = new ClientWebSocket();
await webSocket.ConnectAsync(new Uri($@"ws://localhost:{port}/"), cancellationToken);
channel = new WebSocketChannel(webSocket);
channel.MessageReceived += msg => MessageReceived?.Invoke(msg);
channel.ClosedPrematurely += () => Closed?.Invoke();
channel.Start(cancellationToken);
}
public async Task SendAsync(string message)
{
if (channel == null)
throw new InvalidOperationException($@"Must {nameof(Start)} first.");
await channel.SendAsync(message);
}
public async Task StopAsync(CancellationToken stoppingToken = default)
{
try
{
if (channel != null)
await channel.StopAsync(stoppingToken).ConfigureAwait(false);
}
catch (OperationCanceledException)
{
// has to be caught manually because outer task isn't accepting `stoppingToken`.
}
}
public void Dispose()
{
channel?.Dispose();
}
}
}
+274
View File
@@ -0,0 +1,274 @@
// 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.Threading;
using System.Threading.Tasks;
using NUnit.Framework;
using osu.Game.IPC;
using osu.Game.Online.Multiplayer;
namespace osu.Game.Tests.IPC
{
[TestFixture]
public class WebSocketTest
{
[Test]
public async Task TestClientInitiatedDuplexCommunication()
{
const int port = 54321;
var server = new WebSocketServer(port);
var client = new WebSocketClient(port);
var duplexComplete = new ManualResetEventSlim(false);
server.MessageReceived += (clientId, msg) =>
{
if (msg != "PING")
return;
// ReSharper disable once AccessToDisposedClosure
server.SendAsync(clientId, "PONG").FireAndForget();
};
client.MessageReceived += msg =>
{
if (msg != "PONG")
return;
duplexComplete.Set();
};
await server.StartAsync();
await client.Start();
await client.SendAsync("PING");
Assert.That(duplexComplete.Wait(10_000));
await client.StopAsync();
await server.StopAsync();
client.Dispose();
server.Dispose();
}
[Test]
public async Task TestServerInitiatedDuplexCommunication()
{
const int port = 54321;
var server = new WebSocketServer(port);
var client = new WebSocketClient(port);
var clientConnected = new ManualResetEventSlim();
var duplexComplete = new ManualResetEventSlim();
client.MessageReceived += msg =>
{
if (msg != "PING")
return;
// ReSharper disable once AccessToDisposedClosure
client.SendAsync("PONG").FireAndForget();
};
server.ClientConnected += _ => clientConnected.Set();
server.MessageReceived += (_, msg) =>
{
if (msg != "PONG")
return;
duplexComplete.Set();
};
await server.StartAsync();
await client.Start();
Assert.That(clientConnected.Wait(10_000));
await server.SendAsync(1, "PING");
Assert.That(duplexComplete.Wait(10_000));
await client.StopAsync();
await server.StopAsync();
client.Dispose();
server.Dispose();
}
[Test]
public async Task TestServerBroadcast()
{
const int port = 54321;
const int client_count = 5;
var server = new WebSocketServer(port);
var clients = new List<WebSocketClient>(client_count);
var connectionCountdown = new CountdownEvent(client_count);
var receiptCountdown = new CountdownEvent(client_count);
for (int i = 0; i < client_count; ++i)
{
var client = new WebSocketClient(port);
client.MessageReceived += msg =>
{
if (msg != "HI ALL")
return;
receiptCountdown.Signal();
};
clients.Add(client);
}
server.ClientConnected += _ => connectionCountdown.Signal();
await server.StartAsync();
foreach (var client in clients)
await client.Start();
Assert.That(connectionCountdown.Wait(10_000));
await server.BroadcastAsync("HI ALL");
Assert.That(receiptCountdown.Wait(10_000));
foreach (var client in clients)
{
await client.StopAsync();
client.Dispose();
}
await server.StopAsync();
server.Dispose();
}
[Test]
public async Task TestClientSoftAborts()
{
const int port = 54321;
var server = new WebSocketServer(port);
var client = new WebSocketClient(port);
await server.StartAsync();
await client.Start();
await client.StopAsync();
client.Dispose();
await server.StopAsync();
server.Dispose();
}
[Test]
public async Task TestClientHardAborts()
{
const int port = 54321;
var server = new WebSocketServer(port);
var client = new WebSocketClient(port);
await server.StartAsync();
await client.Start();
await client.StopAsync(new CancellationToken(true));
client.Dispose();
await server.StopAsync();
server.Dispose();
}
[Test]
public async Task TestServerSoftAborts()
{
const int port = 54321;
var server = new WebSocketServer(port);
var client = new WebSocketClient(port);
await server.StartAsync();
await client.Start();
await server.StopAsync();
server.Dispose();
await client.StopAsync();
client.Dispose();
}
[Test]
public async Task TestServerHardAborts()
{
const int port = 54321;
var server = new WebSocketServer(port);
var client = new WebSocketClient(port);
await server.StartAsync();
await client.Start();
await server.StopAsync(new CancellationToken(true));
server.Dispose();
await client.StopAsync();
client.Dispose();
}
[Test]
public async Task TestClientMessageTooLong()
{
const int port = 54321;
var server = new WebSocketServer(port);
var client = new WebSocketClient(port);
var clientClosed = new ManualResetEventSlim();
client.Closed += clientClosed.Set;
await server.StartAsync();
await client.Start();
await client.SendAsync(new string('0', 9999));
Assert.That(clientClosed.Wait(10_000));
await client.StopAsync();
client.Dispose();
var client2 = new WebSocketClient(port);
var duplexComplete = new ManualResetEventSlim();
server.MessageReceived += (clientId, msg) =>
{
if (msg != "PING")
return;
// ReSharper disable once AccessToDisposedClosure
server.SendAsync(clientId, "PONG").FireAndForget();
};
client2.MessageReceived += msg =>
{
if (msg != "PONG")
return;
duplexComplete.Set();
};
await client2.Start();
await client2.SendAsync("PING");
Assert.That(duplexComplete.Wait(10000));
await client2.StopAsync();
await server.StopAsync();
client2.Dispose();
server.Dispose();
}
[Test]
public async Task TestStartStopServerWithoutReceivingClients()
{
const int port = 54321;
var server = new WebSocketServer(port);
await server.StartAsync();
await server.StopAsync();
server.Dispose();
}
}
}
@@ -147,7 +147,7 @@ namespace osu.Game.Tests.NonVisual
foreach (string file in osuStorage.IgnoreFiles)
{
if (!file.Contains(".realm", StringComparison.Ordinal))
if (!file.Contains(".realm", StringComparison.Ordinal) && !file.Contains("AuthNative", StringComparison.Ordinal))
{
Assert.That(File.Exists(Path.Combine(originalDirectory, file)));
Assert.That(storage.Exists(file), Is.False, () => $"{file} exists in destination when it was expected to be ignored");
@@ -660,7 +660,7 @@ namespace osu.Game.Tests.NonVisual.Filtering
public bool Matches(BeatmapInfo beatmapInfo, FilterCriteria criteria) => match;
public bool TryParseCustomKeywordCriteria(string key, Operator op, string value) => false;
public bool FilterMayChangeFromMods(ValueChangedEvent<IReadOnlyList<Mod>> mods) => false;
public bool FilterMayChangeFromMods(FilterCriteria criteria, ValueChangedEvent<IReadOnlyList<Mod>> mods) => false;
}
}
}
@@ -559,7 +559,7 @@ namespace osu.Game.Tests.NonVisual.Filtering
return false;
}
public bool FilterMayChangeFromMods(ValueChangedEvent<IReadOnlyList<Mod>> mods) => false;
public bool FilterMayChangeFromMods(FilterCriteria criteria, ValueChangedEvent<IReadOnlyList<Mod>> mods) => false;
}
private static readonly object[] correct_date_query_examples =
@@ -82,11 +82,7 @@ namespace osu.Game.Tests.Visual.Gameplay
{
base.Update();
List<Vector2> vertices = new List<Vector2>();
path.GetPathToProgress(vertices, 0, 1);
drawablePath.Vertices = vertices;
drawablePath.Vertices = path.CalculatedPath;
controlPointDrawablePath.Vertices = path.ControlPoints.Select(o => o.Position).ToList();
if (controlPointDrawablePath.Vertices.Count > 0)
@@ -95,11 +91,7 @@ namespace osu.Game.Tests.Visual.Gameplay
drawablePath.PositionInBoundingBox(drawablePath.Vertices[0]) - controlPointDrawablePath.PositionInBoundingBox(controlPointDrawablePath.Vertices[0]);
}
vertices.Clear();
convertedPath.GetPathToProgress(vertices, 0, 1);
convertedDrawablePath.Vertices = vertices;
convertedDrawablePath.Vertices = convertedPath.CalculatedPath;
convertedControlPointDrawablePath.Vertices = convertedPath.ControlPoints.Select(o => o.Position).ToList();
if (convertedControlPointDrawablePath.Vertices.Count > 0)
@@ -39,12 +39,7 @@ namespace osu.Game.Tests.Visual.Gameplay
base.Update();
if (path != null)
{
List<Vector2> vertices = new List<Vector2>();
path.GetPathToProgress(vertices, 0, 1);
drawablePath.Vertices = vertices;
}
drawablePath.Vertices = path.CalculatedPath;
}
[Test]
@@ -1,17 +1,19 @@
// 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;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Extensions;
using osu.Framework.Testing;
using osu.Framework.Utils;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Online.Matchmaking;
using osu.Game.Online.Multiplayer;
using osu.Game.Online.Multiplayer.MatchTypes.RankedPlay;
using osu.Game.Online.Rooms;
using osu.Game.Screens.OnlinePlay.Matchmaking.Intro;
using osu.Game.Screens.OnlinePlay.Matchmaking.Queue;
using osu.Game.Tests.Visual.Multiplayer;
using osu.Game.Users;
namespace osu.Game.Tests.Visual.Matchmaking
{
@@ -27,24 +29,37 @@ namespace osu.Game.Tests.Visual.Matchmaking
{
base.SetUpSteps();
AddStep("join room", () => JoinRoom(CreateDefaultRoom(MatchType.Matchmaking)));
WaitForJoined();
AddStep("load screen", () => LoadScreen(new ScreenIntro(MatchmakingPoolType.QuickPlay)));
AddUntilStep("wait for queue screen", () => queueScreen?.IsLoaded == true);
AddStep("send status update", () =>
{
int userId1 = Random.Shared.Next(1, 11);
int userId2 = Random.Shared.GetItems(Enumerable.Range(1, 10).Except([userId1]).ToArray(), 1).Single();
MultiplayerClient.MatchmakingLobbyStatusChanged(new MatchmakingLobbyStatus
{
UsersInQueue = Enumerable.Range(1, 10).ToArray(),
RatingDistribution = Enumerable.Range(0, 24).Select(i => (400 + i * 100, (int)Math.Round(generateCount(400 + i * 100, 1600, 400, 7200)))).ToArray(),
UserRating = Random.Shared.Next(400, 2800),
RecentMatches = Enumerable.Range(1, 10).Select(_ => (MatchRoomState)new RankedPlayRoomState
{
Users =
{
{ userId1, new RankedPlayUserInfo { Rating = 0, Life = Random.Shared.Next(0, 1_000_001), RoundsWon = Random.Shared.Next(0, 4) } },
{ userId2, new RankedPlayUserInfo { Rating = 0, Life = Random.Shared.Next(0, 1_000_001), RoundsWon = Random.Shared.Next(0, 4) } },
}
}).ToArray()
}).WaitSafely();
});
}
[Test]
public void TestBasic()
{
AddUntilStep("wait for queue screen", () => queueScreen?.IsLoaded == true);
AddStep("set users", () =>
{
queueScreen!.Users = Enumerable.Range(0, 10).Select(_ => new APIUser
{
Username = "peppy",
Statistics = new UserStatistics { GlobalRank = 1234 },
Id = RNG.Next(2, 30000000),
}).ToArray();
});
AddStep("change state to idle", () => queueScreen!.SetState(ScreenQueue.MatchmakingScreenState.Idle));
AddStep("change state to queueing", () => queueScreen!.SetState(ScreenQueue.MatchmakingScreenState.Queueing));
@@ -55,5 +70,26 @@ namespace osu.Game.Tests.Visual.Matchmaking
AddStep("change state to in room", () => queueScreen!.SetState(ScreenQueue.MatchmakingScreenState.InRoom));
}
[Test]
public void TestDelayedRoomScreenPushDoesNotRunIfRoomIsLeftPrematurely()
{
AddStep("change state to in room then immediately leave room", () =>
{
queueScreen!.SetState(ScreenQueue.MatchmakingScreenState.InRoom);
MultiplayerClient.LeaveRoom();
});
// the queue screen waits 2 seconds between transitioning to `InRoom` state and actually pushing the relevant screen.
// if the room goes to `null` in that time, things die very hard.
// therefore the wait here is to check that things don't die very hard.
// if they do the test will throw an exception and fail.
AddWaitStep("wait a little bit", 10);
}
private static double generateCount(double x, double mean, double stdDev, double amplitude)
{
return amplitude * Math.Exp(-Math.Pow(x - mean, 2) / (2 * Math.Pow(stdDev, 2))) + Random.Shared.Next(300);
}
}
}
@@ -0,0 +1,100 @@
// 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;
using System.Collections.Generic;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Game.Overlays;
using osu.Game.Screens.OnlinePlay.Matchmaking.Queue;
using osuTK;
namespace osu.Game.Tests.Visual.Matchmaking
{
public partial class TestSceneRatingDistributionGraph : OsuTestScene
{
[Cached]
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Plum);
private RatingDistributionGraph graph = null!;
[SetUp]
public void Setup() => Schedule(() =>
{
Child = graph = new RatingDistributionGraph
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
Size = new Vector2(0.5f, 0.25f)
};
});
[Test]
public void TestRandomData()
{
AddStep("set random data", () =>
{
List<(int x, int y)> values = new List<(int x, int y)>();
for (int i = 400; i <= 2800; i += 100)
values.Add((i, (int)Math.Round(generateCount(i, 1600, 400, 7200))));
graph.SetData(values.ToArray(), Random.Shared.Next(400, 2800));
});
}
[Test]
public void TestNoUserRating()
{
AddStep("set data", () =>
{
List<(int x, int y)> values = new List<(int x, int y)>();
for (int i = 400; i <= 2800; i += 100)
values.Add((i, (int)Math.Round(generateCount(i, 1600, 400, 7200))));
graph.SetData(values.ToArray(), null);
});
}
[Test]
public void TestNoData()
{
AddStep("set empty data", () => graph.SetData([], null));
}
[Test]
public void TestOutOfBoundsUserRating()
{
AddStep("set data with max user rating", () =>
{
List<(int x, int y)> values = new List<(int x, int y)>();
for (int i = 400; i <= 2800; i += 100)
values.Add((i, (int)Math.Round(generateCount(i, 1600, 400, 7200))));
graph.SetData(values.ToArray(), 4000);
});
AddStep("set data with min user rating", () =>
{
List<(int x, int y)> values = new List<(int x, int y)>();
for (int i = 400; i <= 2800; i += 100)
values.Add((i, (int)Math.Round(generateCount(i, 1600, 400, 7200))));
graph.SetData(values.ToArray(), 0);
});
AddStep("set data with only user rating", () =>
{
List<(int x, int y)> values = new List<(int x, int y)>();
for (int i = 400; i <= 2800; i += 100)
values.Add((i, (int)Math.Round(generateCount(i, 1600, 400, 7200))));
graph.SetData([], 1500);
});
}
private static double generateCount(double x, double mean, double stdDev, double amplitude)
{
return amplitude * Math.Exp(-Math.Pow(x - mean, 2) / (2 * Math.Pow(stdDev, 2))) + Random.Shared.Next(300);
}
}
}
@@ -12,7 +12,6 @@ using osu.Framework.Extensions.TypeExtensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Testing;
using osu.Game.Graphics.UserInterface;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Online.Metadata;
@@ -219,13 +218,13 @@ namespace osu.Game.Tests.Visual.Online
}
private void waitForLoad()
=> AddUntilStep("wait for panels to load", () => this.ChildrenOfType<LoadingSpinner>().First().State.Value, () => Is.EqualTo(Visibility.Hidden));
=> AddUntilStep("wait for panels to load", () => this.ChildrenOfType<UserPanel>().Any());
private void assertVisiblePanelCount<T>(int expectedVisible)
where T : UserPanel
{
AddAssert($"{typeof(T).ReadableName()}s in list", () => this.ChildrenOfType<FriendsList>().Last().ChildrenOfType<UserPanel>().All(p => p is T));
AddAssert($"{expectedVisible} panels visible", () => this.ChildrenOfType<FriendsList>().Last().ChildrenOfType<FriendsList.FilterableUserPanel>().Count(p => p.IsPresent),
AddUntilStep($"{typeof(T).ReadableName()}s in list", () => this.ChildrenOfType<FriendsList>().Last().ChildrenOfType<UserPanel>().All(p => p is T));
AddUntilStep($"{expectedVisible} panels visible", () => this.ChildrenOfType<FriendsList>().Last().ChildrenOfType<FriendsList.FilterableUserPanel>().Count(p => p.IsPresent),
() => Is.EqualTo(expectedVisible));
}
@@ -0,0 +1,89 @@
// 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 osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Testing;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Overlays;
using osu.Game.Overlays.Profile;
using osu.Game.Overlays.Profile.Header.Components;
using osu.Game.Rulesets.Osu;
using osuTK;
namespace osu.Game.Tests.Visual.Online
{
public partial class TestSceneUserProfileMatchmakingStatsDisplay : OsuManualInputManagerTestScene
{
[Cached]
private readonly Bindable<UserProfileData?> userProfileData = new Bindable<UserProfileData?>(new UserProfileData(new APIUser(), new OsuRuleset().RulesetInfo));
[Cached]
private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Pink);
[SetUpSteps]
public void SetUpSteps()
{
AddStep("create", () =>
{
Clear();
Add(new Box
{
RelativeSizeAxes = Axes.Both,
Colour = colourProvider.Background2,
});
Add(new MatchmakingStatsDisplay
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Scale = new Vector2(1f),
User = { BindTarget = userProfileData },
});
});
AddStep("set stats", () => userProfileData.Value = new UserProfileData(new APIUser
{
MatchmakingStatistics =
[
new APIUserMatchmakingStatistics
{
Plays = 10,
FirstPlacements = 8,
Rank = 1000,
Rating = 2000,
TotalPoints = 500,
Pool =
{
Name = "Active Pool"
}
},
new APIUserMatchmakingStatistics
{
Plays = 5,
FirstPlacements = 4,
Rank = 500,
Rating = 1000,
TotalPoints = 250,
Pool =
{
Name = "Inactive Pool"
}
},
new APIUserMatchmakingStatistics
{
Rating = 1500,
IsRatingProvisional = true,
Pool =
{
Name = "Provisional"
}
}
]
}, new OsuRuleset().RulesetInfo));
AddStep("clear stats", () => userProfileData.Value = null);
}
}
}
@@ -0,0 +1,24 @@
// 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 NUnit.Framework;
using osu.Framework.Allocation;
using osu.Game.Overlays;
using osu.Game.Overlays.Dashboard.UserSearch;
namespace osu.Game.Tests.Visual.Online
{
public partial class TestSceneUserSearchDisplay : OsuTestScene
{
[Cached]
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple);
protected override bool UseOnlineAPI => true;
[SetUp]
public void Setup() => Schedule(() =>
{
Child = new UserSearchDisplay();
});
}
}
@@ -32,8 +32,6 @@ namespace osu.Game.Tests.Visual.RankedPlay
AddStep("set pick state", () => MultiplayerClient.RankedPlayChangeStage(RankedPlayStage.CardPlay, state => state.ActiveUserId = 2).WaitSafely());
AddWaitStep("wait some", 5);
AddStep("reveal cards", () =>
{
for (int i = 0; i < 5; i++)
@@ -46,6 +44,15 @@ namespace osu.Game.Tests.Visual.RankedPlay
}).WaitSafely();
}
});
AddWaitStep("wait", 15);
AddStep("play beatmap", () => MultiplayerClient.PlayUserCard(2, hand => hand[0]).WaitSafely());
AddStep("reveal card", () => MultiplayerClient.RankedPlayRevealUserCard(2, hand => hand[0], new MultiplayerPlaylistItem
{
ID = 0,
BeatmapID = requestHandler.Beatmaps[0].OnlineID
}).WaitSafely());
}
}
}
@@ -1,12 +1,17 @@
// 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 osu.Framework.Extensions;
using osu.Framework.Testing;
using osu.Game.Graphics.UserInterface;
using osu.Game.Online.API;
using osu.Game.Online.Multiplayer;
using osu.Game.Online.Multiplayer.MatchTypes.RankedPlay;
using osu.Game.Online.Rooms;
using osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay;
using osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay.Hand;
using osuTK.Input;
namespace osu.Game.Tests.Visual.RankedPlay
{
@@ -46,6 +51,30 @@ namespace osu.Game.Tests.Visual.RankedPlay
}).WaitSafely();
}
});
for (int i = 0; i < 3; i++)
{
int i2 = i;
AddStep($"click card {i2}", () =>
{
InputManager.MoveMouseTo(this.ChildrenOfType<PlayerHandOfCards.PlayerHandCard>().ElementAt(i2));
InputManager.Click(MouseButton.Left);
});
}
AddWaitStep("wait", 3);
AddStep("click play button", () =>
{
var button = screen
.ChildrenOfType<PlayerHandOfCards.PlayerHandCard>()
.First(it => it.Selected)
.ChildrenOfType<ShearedButton>()
.First();
InputManager.MoveMouseTo(button);
InputManager.Click(MouseButton.Left);
});
}
}
}
@@ -56,14 +56,14 @@ namespace osu.Game.Tests.Visual.RankedPlay
});
AddStep("single selection mode", () => handOfCards.SelectionMode = HandSelectionMode.Single);
AddStep("click first card", () => handOfCards.Cards.First().TriggerClick());
AddAssert("first card selected", () => handOfCards.Selection.SequenceEqual([handOfCards.Cards.First().Item]));
AddStep("click first card", () => handOfCards.GetCardsInDisplayOrder()[0].TriggerClick());
AddAssert("first card selected", () => handOfCards.Selection.SequenceEqual([handOfCards.GetCardsInDisplayOrder()[0].Item]));
AddStep("click second card", () => handOfCards.Cards.ElementAt(1).TriggerClick());
AddAssert("second card selected", () => handOfCards.Selection.SequenceEqual([handOfCards.Cards.ElementAt(1).Item]));
AddStep("click second card", () => handOfCards.GetCardsInDisplayOrder()[1].TriggerClick());
AddAssert("second card selected", () => handOfCards.Selection.SequenceEqual([handOfCards.GetCardsInDisplayOrder()[1].Item]));
AddStep("click second card again", () => handOfCards.Cards.ElementAt(1).TriggerClick());
AddAssert("second card selected", () => handOfCards.Selection.SequenceEqual([handOfCards.Cards.ElementAt(1).Item]));
AddStep("click second card again", () => handOfCards.GetCardsInDisplayOrder()[1].TriggerClick());
AddAssert("second card selected", () => handOfCards.Selection.SequenceEqual([handOfCards.GetCardsInDisplayOrder()[1].Item]));
}
[Test]
@@ -76,14 +76,14 @@ namespace osu.Game.Tests.Visual.RankedPlay
});
AddStep("multi selection mode", () => handOfCards.SelectionMode = HandSelectionMode.Multiple);
AddStep("click first card", () => handOfCards.Cards.First().TriggerClick());
AddAssert("first card selected", () => handOfCards.Selection.SequenceEqual([handOfCards.Cards.First().Item]));
AddStep("click first card", () => handOfCards.GetCardsInDisplayOrder().First().TriggerClick());
AddAssert("first card selected", () => handOfCards.Selection.SequenceEqual([handOfCards.GetCardsInDisplayOrder().First().Item]));
AddStep("click second card", () => handOfCards.Cards.ElementAt(1).TriggerClick());
AddAssert("both cards selected", () => handOfCards.Selection.SequenceEqual([handOfCards.Cards.ElementAt(0).Item, handOfCards.Cards.ElementAt(1).Item]));
AddStep("click second card", () => handOfCards.GetCardsInDisplayOrder()[1].TriggerClick());
AddAssert("both cards selected", () => handOfCards.Selection.SequenceEqual([handOfCards.GetCardsInDisplayOrder()[0].Item, handOfCards.GetCardsInDisplayOrder()[1].Item]));
AddStep("click second card again", () => handOfCards.Cards.ElementAt(1).TriggerClick());
AddAssert("first card selected", () => handOfCards.Selection.SequenceEqual([handOfCards.Cards.ElementAt(0).Item]));
AddStep("click second card again", () => handOfCards.GetCardsInDisplayOrder()[1].TriggerClick());
AddAssert("first card selected", () => handOfCards.Selection.SequenceEqual([handOfCards.GetCardsInDisplayOrder()[0].Item]));
}
[Test]
@@ -131,20 +131,20 @@ namespace osu.Game.Tests.Visual.RankedPlay
Key key = Key.Number1 + i;
AddStep($"key {i + 1}", () => InputManager.Key(key));
AddAssert("first card selected", () => handOfCards.Selection.SequenceEqual([handOfCards.Cards.ElementAt(i1).Item]));
AddAssert("first card selected", () => handOfCards.Selection.SequenceEqual([handOfCards.GetCardsInDisplayOrder()[i1].Item]));
}
AddStep("right arrow", () => InputManager.Key(Key.Right));
AddAssert("first card selected", () => handOfCards.Selection.SequenceEqual([handOfCards.Cards.ElementAt(0).Item]));
AddAssert("first card selected", () => handOfCards.Selection.SequenceEqual([handOfCards.GetCardsInDisplayOrder()[0].Item]));
AddStep("right arrow", () => InputManager.Key(Key.Right));
AddAssert("second card selected", () => handOfCards.Selection.SequenceEqual([handOfCards.Cards.ElementAt(1).Item]));
AddAssert("second card selected", () => handOfCards.Selection.SequenceEqual([handOfCards.GetCardsInDisplayOrder()[1].Item]));
AddStep("left arrow", () => InputManager.Key(Key.Left));
AddAssert("first card selected", () => handOfCards.Selection.SequenceEqual([handOfCards.Cards.ElementAt(0).Item]));
AddAssert("first card selected", () => handOfCards.Selection.SequenceEqual([handOfCards.GetCardsInDisplayOrder()[0].Item]));
AddStep("left arrow", () => InputManager.Key(Key.Left));
AddAssert("last card selected", () => handOfCards.Selection.SequenceEqual([handOfCards.Cards.ElementAt(^1).Item]));
AddAssert("last card selected", () => handOfCards.Selection.SequenceEqual([handOfCards.GetCardsInDisplayOrder()[^1].Item]));
AddStep("space", () => InputManager.Key(Key.Space));
AddAssert("play action triggered", () => playActionTriggered);
@@ -166,11 +166,11 @@ namespace osu.Game.Tests.Visual.RankedPlay
Key key = Key.Number1 + i;
AddStep($"key {i + 1}", () => InputManager.Key(key));
AddAssert("card hovered", () => handOfCards.Cards.ElementAt(i1).CardHovered);
AddAssert("card hovered", () => handOfCards.GetCardsInDisplayOrder()[i1].CardHovered);
AddAssert("card not selected", () => !handOfCards.Selection.Contains(handOfCards.Cards.ElementAt(i1).Card.Item));
AddAssert("card not selected", () => !handOfCards.Selection.Contains(handOfCards.GetCardsInDisplayOrder()[i1].Card.Item));
AddStep("space", () => InputManager.Key(Key.Space));
AddAssert("card selected", () => handOfCards.Selection.Contains(handOfCards.Cards.ElementAt(i1).Card.Item));
AddAssert("card selected", () => handOfCards.Selection.Contains(handOfCards.GetCardsInDisplayOrder()[i1].Card.Item));
}
}
@@ -192,5 +192,32 @@ namespace osu.Game.Tests.Visual.RankedPlay
.All(card => !card.ScreenSpaceDrawQuad.AABBFloat.IntersectsWith(handOfCards.ScreenSpaceDrawQuad.AABBFloat))
);
}
[Test]
public void TestRemoveCardsWhileDragging()
{
AddStep("add cards", () =>
{
for (int i = 0; i < 5; i++)
handOfCards.AddCard(new RankedPlayCardWithPlaylistItem(new RankedPlayCardItem()));
});
AddStep("hover card", () => InputManager.MoveMouseTo(handOfCards.GetCardsInDisplayOrder()[0]));
AddStep("start drag", () => InputManager.PressButton(MouseButton.Left));
AddStep("move card", () => InputManager.MoveMouseTo(handOfCards.GetCardsInDisplayOrder()[3]));
AddStep("remove cards", () =>
{
foreach (var card in handOfCards.Cards.ToArray())
handOfCards.RemoveCard(card.Item);
});
AddStep("release mouse", () => InputManager.ReleaseButton(MouseButton.Left));
}
[Test]
public void TestKeyboardSelectionWithoutCards()
{
AddAssert("no cards", () => !handOfCards.Cards.Any());
AddStep("right arrow", () => InputManager.Key(Key.Right));
AddStep("left arrow", () => InputManager.Key(Key.Left));
}
}
}
@@ -17,7 +17,6 @@ namespace osu.Game.Tests.Visual.RankedPlay
private readonly Bindable<Colour4> gradientOuter = new Bindable<Colour4>(Color4Extensions.FromHex("AC6D97"));
private readonly Bindable<Colour4> gradientInner = new Bindable<Colour4>(Color4Extensions.FromHex("544483"));
private readonly Bindable<Colour4> dots = new Bindable<Colour4>(Color4Extensions.FromHex("D56CF6"));
public TestSceneRankedPlayBackground()
{
@@ -40,11 +39,6 @@ namespace osu.Game.Tests.Visual.RankedPlay
Scale = new Vector2(0.4f),
Current = gradientInner,
},
new BasicColourPicker
{
Scale = new Vector2(0.4f),
Current = dots,
}
]
}
];
@@ -54,9 +48,8 @@ namespace osu.Game.Tests.Visual.RankedPlay
{
base.LoadComplete();
gradientOuter.BindValueChanged(e => background.GradientOutside = e.NewValue, true);
gradientInner.BindValueChanged(e => background.GradientInside = e.NewValue, true);
dots.BindValueChanged(e => background.DotsColour = e.NewValue, true);
gradientOuter.BindValueChanged(e => background.GradientBottom = e.NewValue, true);
gradientInner.BindValueChanged(e => background.GradientTop = e.NewValue, true);
}
}
}
@@ -25,18 +25,18 @@ namespace osu.Game.Tests.Visual.RankedPlay
{
Children =
[
new RankedPlayCornerPiece(RankedPlayColourScheme.Blue, Anchor.BottomLeft)
new RankedPlayCornerPiece(RankedPlayColourScheme.BLUE, Anchor.BottomLeft)
{
State = { BindTarget = visibility },
Child = new RankedPlayUserDisplay(new APIUser { Id = 2, Username = "peppy" }, Anchor.BottomLeft, RankedPlayColourScheme.Blue)
Child = new RankedPlayUserDisplay(new APIUser { Id = 2, Username = "peppy" }, Anchor.BottomLeft, RankedPlayColourScheme.BLUE)
{
RelativeSizeAxes = Axes.Both,
}
},
new RankedPlayCornerPiece(RankedPlayColourScheme.Red, Anchor.TopRight)
new RankedPlayCornerPiece(RankedPlayColourScheme.RED, Anchor.TopRight)
{
State = { BindTarget = visibility },
Child = new RankedPlayUserDisplay(new APIUser { Id = 2, Username = "peppy" }, Anchor.TopRight, RankedPlayColourScheme.Red)
Child = new RankedPlayUserDisplay(new APIUser { Id = 2, Username = "peppy" }, Anchor.TopRight, RankedPlayColourScheme.RED)
{
RelativeSizeAxes = Axes.Both,
}
@@ -0,0 +1,74 @@
// 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 NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Online.Multiplayer.MatchTypes.RankedPlay;
using osu.Game.Overlays;
using osu.Game.Screens.OnlinePlay.Matchmaking.Queue;
using osu.Game.Tests.Visual.Multiplayer;
namespace osu.Game.Tests.Visual.RankedPlay
{
public partial class TestSceneRankedPlayMatchPanel : MultiplayerTestScene
{
[Cached]
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Plum);
[Test]
public void TestLeftWin()
{
AddStep("add panel", () => Child = new DelayedLoadWrapper(new RankedPlayMatchPanel(new RankedPlayRoomState
{
Users =
{
{ 1, new RankedPlayUserInfo { Rating = 0, Life = 800_000, RoundsWon = 3 } },
{ 2, new RankedPlayUserInfo { Rating = 0, Life = 200_000, RoundsWon = 1 } }
}
}), 0)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Width = 280
});
}
[Test]
public void TestRightWin()
{
AddStep("add panel", () => Child = new DelayedLoadWrapper(new RankedPlayMatchPanel(new RankedPlayRoomState
{
Users =
{
{ 1, new RankedPlayUserInfo { Rating = 0, Life = 200_000, RoundsWon = 3 } },
{ 2, new RankedPlayUserInfo { Rating = 0, Life = 800_000, RoundsWon = 1 } }
}
}), 0)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Width = 280
});
}
[Test]
public void TestDraw()
{
AddStep("add panel", () => Child = new DelayedLoadWrapper(new RankedPlayMatchPanel(new RankedPlayRoomState
{
Users =
{
{ 1, new RankedPlayUserInfo { Rating = 0, Life = 200_000, RoundsWon = 3 } },
{ 2, new RankedPlayUserInfo { Rating = 0, Life = 200_000, RoundsWon = 1 } }
}
}), 0)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Width = 280
});
}
}
}
@@ -8,9 +8,11 @@ using osu.Framework.Testing;
using osu.Game.Graphics.UserInterface;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Online.Multiplayer;
using osu.Game.Online.Multiplayer.MatchTypes.RankedPlay;
using osu.Game.Online.Rooms;
using osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay;
using osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay.Card;
using osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay.Hand;
using osuTK.Input;
@@ -26,21 +28,35 @@ namespace osu.Game.Tests.Visual.RankedPlay
AddStep("join room", () => JoinRoom(CreateDefaultRoom(MatchType.RankedPlay)));
WaitForJoined();
AddStep("join other user", () => MultiplayerClient.AddUser(new APIUser { Id = 2 }));
AddStep("load screen", () => LoadScreen(screen = new RankedPlayScreen(MultiplayerClient.ClientRoom!)));
}
[Test]
public void TestIntroStage()
{
AddStep("join other user", () => MultiplayerClient.AddUser(new APIUser { Id = 2 }));
AddStep("load screen", () => LoadScreen(screen = new RankedPlayScreen(MultiplayerClient.ClientRoom!)));
AddStep("set round warmup phase", () => MultiplayerClient.RankedPlayChangeStage(RankedPlayStage.RoundWarmup, s => s.StarRating = 6.3f).WaitSafely());
}
[Test]
public void TestUnresolvedUser()
{
AddStep("join other user", () => MultiplayerClient.AddUser(new APIUser { Id = TestUserLookupCache.UNRESOLVED_USER_ID }));
AddStep("load screen", () => LoadScreen(screen = new RankedPlayScreen(MultiplayerClient.ClientRoom!)));
AddStep("set round warmup phase", () => MultiplayerClient.RankedPlayChangeStage(RankedPlayStage.RoundWarmup, s => s.StarRating = 6.3f).WaitSafely());
}
[Test]
public void TestDiscardCardsStage()
{
AddStep("join other user", () => MultiplayerClient.AddUser(new APIUser { Id = 2 }));
AddStep("load screen", () => LoadScreen(screen = new RankedPlayScreen(MultiplayerClient.ClientRoom!)));
AddStep("set discard phase", () => MultiplayerClient.RankedPlayChangeStage(RankedPlayStage.CardDiscard).WaitSafely());
AddWaitStep("wait", 3);
@@ -72,6 +88,10 @@ namespace osu.Game.Tests.Visual.RankedPlay
[Test]
public void TestAddRemoveCards()
{
AddStep("join other user", () => MultiplayerClient.AddUser(new APIUser { Id = 2 }));
AddStep("load screen", () => LoadScreen(screen = new RankedPlayScreen(MultiplayerClient.ClientRoom!)));
AddStep("set discard phase", () => MultiplayerClient.RankedPlayChangeStage(RankedPlayStage.CardDiscard).WaitSafely());
for (int i = 0; i < 3; i++)
@@ -84,6 +104,10 @@ namespace osu.Game.Tests.Visual.RankedPlay
[Test]
public void TestRevealCards()
{
AddStep("join other user", () => MultiplayerClient.AddUser(new APIUser { Id = 2 }));
AddStep("load screen", () => LoadScreen(screen = new RankedPlayScreen(MultiplayerClient.ClientRoom!)));
var requestHandler = new BeatmapRequestHandler();
AddStep("setup request handler", () => ((DummyAPIAccess)API).HandleRequest = requestHandler.HandleRequest);
@@ -104,6 +128,10 @@ namespace osu.Game.Tests.Visual.RankedPlay
[Test]
public void TestPlayCardDirect()
{
AddStep("join other user", () => MultiplayerClient.AddUser(new APIUser { Id = 2 }));
AddStep("load screen", () => LoadScreen(screen = new RankedPlayScreen(MultiplayerClient.ClientRoom!)));
AddStep("set play phase", () => MultiplayerClient.RankedPlayChangeStage(RankedPlayStage.CardPlay, state => state.ActiveUserId = API.LocalUser.Value.OnlineID).WaitSafely());
AddWaitStep("wait", 3);
AddStep("play card", () => MultiplayerClient.PlayCard(hand => hand[0]).WaitSafely());
@@ -112,6 +140,10 @@ namespace osu.Game.Tests.Visual.RankedPlay
[Test]
public void TestDiscardCardsDirect()
{
AddStep("join other user", () => MultiplayerClient.AddUser(new APIUser { Id = 2 }));
AddStep("load screen", () => LoadScreen(screen = new RankedPlayScreen(MultiplayerClient.ClientRoom!)));
AddStep("set discard phase", () => MultiplayerClient.RankedPlayChangeStage(RankedPlayStage.CardDiscard).WaitSafely());
AddWaitStep("wait", 3);
AddStep("discard cards", () => MultiplayerClient.DiscardCards(hand => hand.Take(3)).WaitSafely());
@@ -122,6 +154,10 @@ namespace osu.Game.Tests.Visual.RankedPlay
[Test]
public void TestPlayStage()
{
AddStep("join other user", () => MultiplayerClient.AddUser(new APIUser { Id = 2 }));
AddStep("load screen", () => LoadScreen(screen = new RankedPlayScreen(MultiplayerClient.ClientRoom!)));
AddStep("set play phase", () => MultiplayerClient.RankedPlayChangeStage(RankedPlayStage.CardPlay, state => state.ActiveUserId = API.LocalUser.Value.OnlineID).WaitSafely());
AddUntilStep("wait until cards are present", () => this.ChildrenOfType<PlayerHandOfCards.PlayerHandCard>().Count() == 5);
@@ -153,6 +189,10 @@ namespace osu.Game.Tests.Visual.RankedPlay
[Test]
public void TestOtherPlaysCard()
{
AddStep("join other user", () => MultiplayerClient.AddUser(new APIUser { Id = 2 }));
AddStep("load screen", () => LoadScreen(screen = new RankedPlayScreen(MultiplayerClient.ClientRoom!)));
AddStep("set play phase", () => MultiplayerClient.RankedPlayChangeStage(RankedPlayStage.CardPlay, state => state.ActiveUserId = 2).WaitSafely());
AddWaitStep("wait", 5);
AddStep("play beatmap", () => MultiplayerClient.PlayUserCard(2, hand => hand[0]).WaitSafely());
@@ -166,11 +206,51 @@ namespace osu.Game.Tests.Visual.RankedPlay
[Test]
public void TestHealthChange()
{
AddStep("join other user", () => MultiplayerClient.AddUser(new APIUser { Id = 2 }));
AddStep("load screen", () => LoadScreen(screen = new RankedPlayScreen(MultiplayerClient.ClientRoom!)));
AddStep("set play phase", () => MultiplayerClient.RankedPlayChangeStage(RankedPlayStage.CardPlay, state => state.ActiveUserId = 2).WaitSafely());
AddWaitStep("wait", 5);
AddStep("change player 1 health", () => MultiplayerClient.RankedPlayChangeUserState(MultiplayerClient.LocalUser!.UserID, state => state.Life = 250_000).WaitSafely());
AddWaitStep("wait", 5);
AddStep("change player 2 health", () => MultiplayerClient.RankedPlayChangeUserState(2, state => state.Life = 250_000).WaitSafely());
}
[Test]
public void TestPreviewStopsOnEnteringGameplay()
{
AddStep("join other user", () => MultiplayerClient.AddUser(new APIUser { Id = 2 }));
AddStep("load screen", () => LoadScreen(screen = new RankedPlayScreen(MultiplayerClient.ClientRoom!)));
var requestHandler = new BeatmapRequestHandler();
AddStep("setup request handler", () => ((DummyAPIAccess)API).HandleRequest = requestHandler.HandleRequest);
AddStep("set play phase", () => MultiplayerClient.RankedPlayChangeStage(RankedPlayStage.CardPlay, state => state.ActiveUserId = 1001).WaitSafely());
for (int i = 0; i < 3; i++)
{
int i2 = i;
AddStep("reveal card", () => MultiplayerClient.RankedPlayRevealCard(hand => hand[i2], new MultiplayerPlaylistItem
{
ID = i2,
BeatmapID = requestHandler.Beatmaps[i2].OnlineID
}).WaitSafely());
}
AddStep("hover first card", () => InputManager.MoveMouseTo(this.ChildrenOfType<PlayerHandOfCards>().Single().Cards.First()));
AddUntilStep("preview playing", () => this.ChildrenOfType<RankedPlayCard.SongPreviewContainer>().Any(p => p.IsRunning), () => Is.True);
AddWaitStep("wait", 1);
AddStep("play beatmap", () => MultiplayerClient.PlayUserCard(1001, hand => hand[0]).WaitSafely());
AddStep("set warmup", () => MultiplayerClient.RankedPlayChangeStage(RankedPlayStage.GameplayWarmup).WaitSafely());
AddUntilStep("preview running", () => this.ChildrenOfType<RankedPlayCard.SongPreviewContainer>().Any(p => p.IsRunning), () => Is.True);
AddStep("load requested", () => ((IMultiplayerClient)MultiplayerClient).LoadRequested());
AddUntilStep("preview stopped", () => this.ChildrenOfType<RankedPlayCard.SongPreviewContainer>().Any(p => p.IsRunning), () => Is.False);
}
}
}
@@ -40,21 +40,24 @@ namespace osu.Game.Tests.Visual.RankedPlay
[Test]
public void TestBasic()
{
AddStep("create", () => Child = new RankedPlayStageOverlay("Pick Phase", RankedPlayColourScheme.Blue)
double multiplier = 1.0;
AddSliderStep<double>("set multiplier", 1, 5, 2, value => multiplier = value);
AddStep("create", () => Child = new RankedPlayStageOverlay("Pick Phase", RankedPlayColourScheme.BLUE)
{
PickingUser = new APIUser
{
Id = 2,
Username = "peppy",
},
Multiplier = 2,
Multiplier = multiplier,
});
}
[Test]
public void TestLongUsername()
{
AddStep("create", () => Child = new RankedPlayStageOverlay("Pick Phase", RankedPlayColourScheme.Blue)
AddStep("create", () => Child = new RankedPlayStageOverlay("Pick Phase", RankedPlayColourScheme.BLUE)
{
PickingUser = new APIUser
{
@@ -68,7 +71,7 @@ namespace osu.Game.Tests.Visual.RankedPlay
[Test]
public void TestColourScheme()
{
AddStep("create blue", () => Child = new RankedPlayStageOverlay("Pick Phase", RankedPlayColourScheme.Blue)
AddStep("create blue", () => Child = new RankedPlayStageOverlay("Pick Phase", RankedPlayColourScheme.BLUE)
{
PickingUser = new APIUser
{
@@ -77,7 +80,7 @@ namespace osu.Game.Tests.Visual.RankedPlay
},
Multiplier = 2,
});
AddStep("create red", () => Child = new RankedPlayStageOverlay("Pick Phase", RankedPlayColourScheme.Red)
AddStep("create red", () => Child = new RankedPlayStageOverlay("Pick Phase", RankedPlayColourScheme.RED)
{
PickingUser = new APIUser
{
@@ -35,7 +35,7 @@ namespace osu.Game.Tests.Visual.RankedPlay
AddStep("join room", () => JoinRoom(CreateDefaultRoom(MatchType.RankedPlay)));
WaitForJoined();
AddStep("add display", () => Child = new RankedPlayUserDisplay(new APIUser { Id = 1001, Username = "User 1001" }, Anchor.BottomLeft, RankedPlayColourScheme.Blue)
AddStep("add display", () => Child = new RankedPlayUserDisplay(new APIUser { Id = 1001, Username = "User 1001" }, Anchor.BottomLeft, RankedPlayColourScheme.BLUE)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
@@ -47,7 +47,7 @@ namespace osu.Game.Tests.Visual.RankedPlay
[Test]
public void TesUserDisplay()
{
AddStep("blue color scheme", () => Child = new RankedPlayUserDisplay(new APIUser { Id = 1001, Username = "User 1001" }, Anchor.BottomLeft, RankedPlayColourScheme.Blue)
AddStep("blue color scheme", () => Child = new RankedPlayUserDisplay(new APIUser { Id = 1001, Username = "User 1001" }, Anchor.BottomLeft, RankedPlayColourScheme.BLUE)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
@@ -55,7 +55,7 @@ namespace osu.Game.Tests.Visual.RankedPlay
Health = { BindTarget = health }
});
AddStep("red color scheme", () => Child = new RankedPlayUserDisplay(new APIUser { Id = 1001, Username = "User 1001" }, Anchor.BottomLeft, RankedPlayColourScheme.Red)
AddStep("red color scheme", () => Child = new RankedPlayUserDisplay(new APIUser { Id = 1001, Username = "User 1001" }, Anchor.BottomLeft, RankedPlayColourScheme.RED)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
@@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Extensions;
using osu.Framework.Screens;
using osu.Framework.Utils;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests.Responses;
@@ -38,6 +39,44 @@ namespace osu.Game.Tests.Visual.RankedPlay
setupRequestHandler();
}
[Test]
[Explicit("Test exercises correct stopping of audio playback. Has no assertions, only useful when checked manually by a human.")]
public void TestAllSamplesStopOnExit()
{
AddStep("set results state", () => MultiplayerClient.RankedPlayChangeStage(RankedPlayStage.Results, state =>
{
int losingPlayer = state.Users.Keys.First();
foreach (var (id, userInfo) in state.Users)
{
if (id == losingPlayer)
{
userInfo.DamageInfo = new RankedPlayDamageInfo
{
RawDamage = 123_456,
Damage = 123_456,
OldLife = 500_000,
NewLife = 500_000 - 123_456,
};
userInfo.Life = 500_000 - 123_456;
}
else
{
userInfo.DamageInfo = new RankedPlayDamageInfo
{
RawDamage = 0,
Damage = 0,
OldLife = 1_000_000,
NewLife = 1_000_000,
};
}
}
}).WaitSafely());
AddWaitStep("wait for samples to start playing", 5);
AddRepeatStep("exit", () => screen.Exit(), 2);
}
[Test]
public void TestBasic()
{
@@ -0,0 +1,33 @@
// 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 NUnit.Framework;
using osu.Framework.Graphics;
using osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay.Intro;
namespace osu.Game.Tests.Visual.RankedPlay
{
[TestFixture]
public partial class TestSceneStarRatingSequence : RankedPlayTestScene
{
[Test]
public void TestBasicAppearance()
{
float starRating = 5;
AddSliderStep("set star rating", 0f, 10, 5, sr => starRating = sr);
AddStep("play sequence", () =>
{
StarRatingSequence sequence;
Child = sequence = new StarRatingSequence
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre
};
double delay = 0;
sequence.Play(ref delay, starRating);
});
}
}
}
@@ -335,6 +335,50 @@ namespace osu.Game.Tests.Visual.UserInterface
AddUntilStep("wait overlay not present", () => !notificationOverlay.IsPresent);
}
[Test]
public void TestProgressSilentDismissal()
{
ProgressNotification notification = null!;
AddStep("add progress notification", () =>
{
notification = new ProgressNotification
{
Text = @"Uploading to BSS...",
CompletionText = "Uploaded to BSS!",
};
notificationOverlay.Post(notification);
progressingNotifications.Add(notification);
});
AddStep("silently dismiss", () => notification.CompleteSilently());
AddAssert("completed", () => notification.State == ProgressNotificationState.Completed);
AddAssert("Completion toast not shown", () => notificationOverlay.ToastCount == 0);
}
[Test]
public void TestProgressSilentDismissalImmediate()
{
ProgressNotification notification = null!;
AddStep("add progress notification", () =>
{
notification = new ProgressNotification
{
Text = @"Uploading to BSS...",
CompletionText = "Uploaded to BSS!",
};
notification.CompleteSilently();
notificationOverlay.Post(notification);
progressingNotifications.Add(notification);
});
AddAssert("completed", () => notification.State == ProgressNotificationState.Completed);
AddAssert("Completion toast not shown", () => notificationOverlay.ToastCount == 0);
}
[Test]
public void TestProgressClick()
{
@@ -13,11 +13,13 @@ using osu.Framework.Screens;
using osu.Framework.Testing;
using osu.Game.Graphics;
using osu.Game.Graphics.UserInterface;
using osu.Game.Input.Bindings;
using osu.Game.Overlays;
using osu.Game.Overlays.Mods;
using osu.Game.Screens;
using osu.Game.Screens.Footer;
using osu.Game.Screens.Select;
using osuTK.Input;
namespace osu.Game.Tests.Visual.UserInterface
{
@@ -142,6 +144,44 @@ namespace osu.Game.Tests.Visual.UserInterface
AddAssert("other buttons returned", () => ScreenFooter.ChildrenOfType<ScreenFooterButton>().Skip(1).All(b => b.ChildrenOfType<Container>().First().Y == 0));
}
[Test]
public void TestButtonsHiddenByExternalOverlayContentCannotBeTriggered()
{
TestScreen screen = null!;
bool buttonTriggered = false;
AddStep("push screen", () =>
{
ShearedOverlayContainer overlay = new TestShearedOverlayContainer();
LoadScreen(screen = new TestScreen
{
Overlay = overlay,
CreateButtons = () => new[]
{
new ScreenFooterButton(overlay)
{
AccentColour = Dependencies.Get<OsuColour>().Orange1,
Icon = FontAwesome.Solid.Toolbox,
Text = "One",
},
new ScreenFooterButton { Text = "Two", Hotkey = GlobalAction.Select, Action = () => buttonTriggered = true },
new ScreenFooterButton { Text = "Three", Action = () => { } },
},
});
});
AddUntilStep("wait until screen is loaded", () => screen.IsCurrentScreen(), () => Is.True);
AddStep("show overlay", () => screen.Overlay.Show());
contentDisplayed();
AddStep("try direct click", () => ScreenFooter.ChildrenOfType<ScreenFooterButton>().ElementAt(1).TriggerClick());
AddAssert("action not triggered", () => buttonTriggered, () => Is.False);
AddStep("try hotkey", () => InputManager.Key(Key.Enter));
AddAssert("action not triggered", () => buttonTriggered, () => Is.False);
}
[Test]
public void TestTemporarilyShowFooter()
{
@@ -22,7 +22,7 @@ namespace osu.Game.Tests.Visual.UserInterface
OsuSpriteText sort;
OsuSpriteText displayStyle;
Add(toolbar = new UserListToolbar(true)
Add(toolbar = new UserListToolbar
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
+4 -6
View File
@@ -20,6 +20,7 @@ using osu.Game.Beatmaps.Formats;
using osu.Game.Database;
using osu.Game.Extensions;
using osu.Game.IO.Archives;
using osu.Game.Localisation;
using osu.Game.Models;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests.Responses;
@@ -372,7 +373,6 @@ namespace osu.Game.Beatmaps
public void ResetAllOffsets()
{
const string reset_complete_message = "All offsets have been reset!";
Realm.Write(r =>
{
var items = r.All<BeatmapInfo>();
@@ -383,7 +383,7 @@ namespace osu.Game.Beatmaps
beatmap.UserSettings.Offset = 0;
}
PostNotification?.Invoke(new ProgressCompletionNotification { Text = reset_complete_message });
PostNotification?.Invoke(new ProgressCompletionNotification { Text = MaintenanceSettingsStrings.AllOffsetsReset });
});
}
@@ -435,12 +435,10 @@ namespace osu.Game.Beatmaps
/// </summary>
public void DeleteVideos(List<BeatmapSetInfo> items, bool silent = false)
{
const string no_videos_message = "No videos found to delete!";
if (items.Count == 0)
{
if (!silent)
PostNotification?.Invoke(new ProgressCompletionNotification { Text = no_videos_message });
PostNotification?.Invoke(new ProgressCompletionNotification { Text = MaintenanceSettingsStrings.NoVideosFoundToDelete });
return;
}
@@ -448,7 +446,7 @@ namespace osu.Game.Beatmaps
{
Progress = 0,
Text = $"Preparing to delete all {HumanisedModelName} videos...",
CompletionText = no_videos_message,
CompletionText = MaintenanceSettingsStrings.NoVideosFoundToDelete,
State = ProgressNotificationState.Active,
};

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