mirror of
https://github.com/ppy/osu.git
synced 2024-11-11 10:07:52 +08:00
Merge branch 'master' into issues/16839-spun-out-rate
This commit is contained in:
commit
692ddd5f52
18
.github/workflows/ci.yml
vendored
18
.github/workflows/ci.yml
vendored
@ -20,10 +20,10 @@ jobs:
|
|||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
- name: Install .NET 5.0.x
|
- name: Install .NET 6.0.x
|
||||||
uses: actions/setup-dotnet@v1
|
uses: actions/setup-dotnet@v1
|
||||||
with:
|
with:
|
||||||
dotnet-version: "5.0.x"
|
dotnet-version: "6.0.x"
|
||||||
|
|
||||||
# FIXME: libavformat is not included in Ubuntu. Let's fix that.
|
# FIXME: libavformat is not included in Ubuntu. Let's fix that.
|
||||||
# https://github.com/ppy/osu-framework/issues/4349
|
# https://github.com/ppy/osu-framework/issues/4349
|
||||||
@ -65,10 +65,10 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
$VM_ASSETS/select-xamarin-sdk-v2.sh --mono=6.12 --android=11.2
|
$VM_ASSETS/select-xamarin-sdk-v2.sh --mono=6.12 --android=11.2
|
||||||
|
|
||||||
- name: Install .NET 5.0.x
|
- name: Install .NET 6.0.x
|
||||||
uses: actions/setup-dotnet@v1
|
uses: actions/setup-dotnet@v1
|
||||||
with:
|
with:
|
||||||
dotnet-version: "5.0.x"
|
dotnet-version: "6.0.x"
|
||||||
|
|
||||||
# Contrary to seemingly any other msbuild, msbuild running on macOS/Mono
|
# Contrary to seemingly any other msbuild, msbuild running on macOS/Mono
|
||||||
# cannot accept .sln(f) files as arguments.
|
# cannot accept .sln(f) files as arguments.
|
||||||
@ -84,10 +84,10 @@ jobs:
|
|||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
- name: Install .NET 5.0.x
|
- name: Install .NET 6.0.x
|
||||||
uses: actions/setup-dotnet@v1
|
uses: actions/setup-dotnet@v1
|
||||||
with:
|
with:
|
||||||
dotnet-version: "5.0.x"
|
dotnet-version: "6.0.x"
|
||||||
|
|
||||||
# Contrary to seemingly any other msbuild, msbuild running on macOS/Mono
|
# Contrary to seemingly any other msbuild, msbuild running on macOS/Mono
|
||||||
# cannot accept .sln(f) files as arguments.
|
# cannot accept .sln(f) files as arguments.
|
||||||
@ -102,17 +102,17 @@ jobs:
|
|||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
# FIXME: Tools won't run in .NET 5.0 unless you install 3.1.x LTS side by side.
|
# FIXME: Tools won't run in .NET 6.0 unless you install 3.1.x LTS side by side.
|
||||||
# https://itnext.io/how-to-support-multiple-net-sdks-in-github-actions-workflows-b988daa884e
|
# https://itnext.io/how-to-support-multiple-net-sdks-in-github-actions-workflows-b988daa884e
|
||||||
- name: Install .NET 3.1.x LTS
|
- name: Install .NET 3.1.x LTS
|
||||||
uses: actions/setup-dotnet@v1
|
uses: actions/setup-dotnet@v1
|
||||||
with:
|
with:
|
||||||
dotnet-version: "3.1.x"
|
dotnet-version: "3.1.x"
|
||||||
|
|
||||||
- name: Install .NET 5.0.x
|
- name: Install .NET 6.0.x
|
||||||
uses: actions/setup-dotnet@v1
|
uses: actions/setup-dotnet@v1
|
||||||
with:
|
with:
|
||||||
dotnet-version: "5.0.x"
|
dotnet-version: "6.0.x"
|
||||||
|
|
||||||
- name: Restore Tools
|
- name: Restore Tools
|
||||||
run: dotnet tool restore
|
run: dotnet tool restore
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="osu! (Second Client)" type="DotNetProject" factoryName=".NET Project" folderName="osu!" activateToolWindowBeforeRun="false">
|
<configuration default="false" name="osu! (Second Client)" type="DotNetProject" factoryName=".NET Project" folderName="osu!" activateToolWindowBeforeRun="false">
|
||||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Desktop/bin/Debug/net5.0/osu!.dll" />
|
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Desktop/bin/Debug/net6.0/osu!.dll" />
|
||||||
<option name="PROGRAM_PARAMETERS" value="--debug-client-id=1" />
|
<option name="PROGRAM_PARAMETERS" value="--debug-client-id=1" />
|
||||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Desktop/bin/Debug/net5.0" />
|
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Desktop/bin/Debug/net6.0" />
|
||||||
<option name="PASS_PARENT_ENVS" value="1" />
|
<option name="PASS_PARENT_ENVS" value="1" />
|
||||||
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
||||||
<option name="USE_MONO" value="0" />
|
<option name="USE_MONO" value="0" />
|
||||||
@ -12,9 +12,9 @@
|
|||||||
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
||||||
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
||||||
<option name="PROJECT_KIND" value="DotNetCore" />
|
<option name="PROJECT_KIND" value="DotNetCore" />
|
||||||
<option name="PROJECT_TFM" value="net5.0" />
|
<option name="PROJECT_TFM" value="net6.0" />
|
||||||
<method v="2">
|
<method v="2">
|
||||||
<option name="Build" />
|
<option name="Build" />
|
||||||
</method>
|
</method>
|
||||||
</configuration>
|
</configuration>
|
||||||
</component>
|
</component>
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
<ItemGroup Label="Code Analysis">
|
<ItemGroup Label="Code Analysis">
|
||||||
<PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3" PrivateAssets="All" />
|
<PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3" PrivateAssets="All" />
|
||||||
<AdditionalFiles Include="$(MSBuildThisFileDirectory)CodeAnalysis\BannedSymbols.txt" />
|
<AdditionalFiles Include="$(MSBuildThisFileDirectory)CodeAnalysis\BannedSymbols.txt" />
|
||||||
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="5.0.3" PrivateAssets="All" />
|
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="6.0.0" PrivateAssets="All" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Code Analysis">
|
<PropertyGroup Label="Code Analysis">
|
||||||
<CodeAnalysisRuleSet>$(MSBuildThisFileDirectory)CodeAnalysis\osu.ruleset</CodeAnalysisRuleSet>
|
<CodeAnalysisRuleSet>$(MSBuildThisFileDirectory)CodeAnalysis\osu.ruleset</CodeAnalysisRuleSet>
|
||||||
@ -32,13 +32,8 @@
|
|||||||
NU1701:
|
NU1701:
|
||||||
DeepEqual is not netstandard-compatible. This is fine since we run tests with .NET Framework anyway.
|
DeepEqual is not netstandard-compatible. This is fine since we run tests with .NET Framework anyway.
|
||||||
This is required due to https://github.com/NuGet/Home/issues/5740
|
This is required due to https://github.com/NuGet/Home/issues/5740
|
||||||
|
|
||||||
CA9998:
|
|
||||||
Microsoft.CodeAnalysis.FxCopAnalyzers has been deprecated.
|
|
||||||
The entire package will be able to be removed after migrating to .NET 5,
|
|
||||||
as analysers are shipped as part of the .NET 5 SDK anyway.
|
|
||||||
-->
|
-->
|
||||||
<NoWarn>$(NoWarn);NU1701;CA9998</NoWarn>
|
<NoWarn>$(NoWarn);NU1701</NoWarn>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Label="Nuget">
|
<PropertyGroup Label="Nuget">
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
|
@ -48,7 +48,7 @@ You can see some examples of custom rulesets by visiting the [custom ruleset dir
|
|||||||
|
|
||||||
Please make sure you have the following prerequisites:
|
Please make sure you have the following prerequisites:
|
||||||
|
|
||||||
- A desktop platform with the [.NET 5.0 SDK](https://dotnet.microsoft.com/download) installed.
|
- A desktop platform with the [.NET 6.0 SDK](https://dotnet.microsoft.com/download) installed.
|
||||||
- When developing with mobile, [Xamarin](https://docs.microsoft.com/en-us/xamarin/) is required, which is shipped together with Visual Studio or [Visual Studio for Mac](https://visualstudio.microsoft.com/vs/mac/).
|
- When developing with mobile, [Xamarin](https://docs.microsoft.com/en-us/xamarin/) is required, which is shipped together with Visual Studio or [Visual Studio for Mac](https://visualstudio.microsoft.com/vs/mac/).
|
||||||
- When working with the codebase, we recommend using an IDE with intelligent code completion and syntax highlighting, such as [Visual Studio 2019+](https://visualstudio.microsoft.com/vs/), [JetBrains Rider](https://www.jetbrains.com/rider/) or [Visual Studio Code](https://code.visualstudio.com/).
|
- When working with the codebase, we recommend using an IDE with intelligent code completion and syntax highlighting, such as [Visual Studio 2019+](https://visualstudio.microsoft.com/vs/), [JetBrains Rider](https://www.jetbrains.com/rider/) or [Visual Studio Code](https://code.visualstudio.com/).
|
||||||
- When running on Linux, please have a system-wide FFmpeg installation available to support video decoding.
|
- When running on Linux, please have a system-wide FFmpeg installation available to support video decoding.
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<RootNamespace>osu.Game.Rulesets.EmptyFreeform.Tests</RootNamespace>
|
<RootNamespace>osu.Game.Rulesets.EmptyFreeform.Tests</RootNamespace>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<RootNamespace>osu.Game.Rulesets.Pippidon.Tests</RootNamespace>
|
<RootNamespace>osu.Game.Rulesets.Pippidon.Tests</RootNamespace>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<RootNamespace>osu.Game.Rulesets.EmptyScrolling.Tests</RootNamespace>
|
<RootNamespace>osu.Game.Rulesets.EmptyScrolling.Tests</RootNamespace>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<RootNamespace>osu.Game.Rulesets.Pippidon.Tests</RootNamespace>
|
<RootNamespace>osu.Game.Rulesets.Pippidon.Tests</RootNamespace>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -52,10 +52,10 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2022.211.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2022.211.0" />
|
||||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2022.204.0" />
|
<PackageReference Include="ppy.osu.Framework.Android" Version="2022.217.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Label="Transitive Dependencies">
|
<ItemGroup Label="Transitive Dependencies">
|
||||||
<!-- Realm needs to be directly referenced in all Xamarin projects, as it will not pull in its transitive dependencies otherwise. -->
|
<!-- Realm needs to be directly referenced in all Xamarin projects, as it will not pull in its transitive dependencies otherwise. -->
|
||||||
<PackageReference Include="Realm" Version="10.8.0" />
|
<PackageReference Include="Realm" Version="10.9.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<Description>A free-to-win rhythm game. Rhythm is just a *click* away!</Description>
|
<Description>A free-to-win rhythm game. Rhythm is just a *click* away!</Description>
|
||||||
@ -26,10 +26,13 @@
|
|||||||
<ItemGroup Label="Package References">
|
<ItemGroup Label="Package References">
|
||||||
<PackageReference Include="Microsoft.NETCore.Targets" Version="5.0.0" />
|
<PackageReference Include="Microsoft.NETCore.Targets" Version="5.0.0" />
|
||||||
<PackageReference Include="Mono.Posix.NETStandard" Version="1.0.0" />
|
<PackageReference Include="Mono.Posix.NETStandard" Version="1.0.0" />
|
||||||
<PackageReference Include="System.IO.Packaging" Version="5.0.0" />
|
<PackageReference Include="System.IO.Packaging" Version="6.0.0" />
|
||||||
<PackageReference Include="ppy.squirrel.windows" Version="1.9.0.5" />
|
<PackageReference Include="ppy.squirrel.windows" Version="1.9.0.5" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.14" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.2.6" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.14">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
|
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
|
||||||
<PackageReference Include="DiscordRichPresence" Version="1.0.175" />
|
<PackageReference Include="DiscordRichPresence" Version="1.0.175" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
@ -9,9 +9,9 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Label="Project References">
|
<ItemGroup Label="Project References">
|
||||||
<ProjectReference Include="..\osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj" />
|
<ProjectReference Include="..\osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -9,6 +9,12 @@ namespace osu.Game.Rulesets.Catch.Difficulty
|
|||||||
{
|
{
|
||||||
public class CatchDifficultyAttributes : DifficultyAttributes
|
public class CatchDifficultyAttributes : DifficultyAttributes
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The perceived approach rate inclusive of rate-adjusting mods (DT/HT/etc).
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Rate-adjusting mods don't directly affect the approach rate difficulty value, but have a perceived effect as a result of adjusting audio timing.
|
||||||
|
/// </remarks>
|
||||||
[JsonProperty("approach_rate")]
|
[JsonProperty("approach_rate")]
|
||||||
public double ApproachRate { get; set; }
|
public double ApproachRate { get; set; }
|
||||||
|
|
||||||
|
@ -9,9 +9,9 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Label="Project References">
|
<ItemGroup Label="Project References">
|
||||||
<ProjectReference Include="..\osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj" />
|
<ProjectReference Include="..\osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -9,9 +9,18 @@ namespace osu.Game.Rulesets.Mania.Difficulty
|
|||||||
{
|
{
|
||||||
public class ManiaDifficultyAttributes : DifficultyAttributes
|
public class ManiaDifficultyAttributes : DifficultyAttributes
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The hit window for a GREAT hit inclusive of rate-adjusting mods (DT/HT/etc).
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Rate-adjusting mods do not affect the hit window at all in osu-stable.
|
||||||
|
/// </remarks>
|
||||||
[JsonProperty("great_hit_window")]
|
[JsonProperty("great_hit_window")]
|
||||||
public double GreatHitWindow { get; set; }
|
public double GreatHitWindow { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The score multiplier applied via score-reducing mods.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("score_multiplier")]
|
[JsonProperty("score_multiplier")]
|
||||||
public double ScoreMultiplier { get; set; }
|
public double ScoreMultiplier { get; set; }
|
||||||
|
|
||||||
|
@ -48,7 +48,9 @@ namespace osu.Game.Rulesets.Mania.Difficulty
|
|||||||
{
|
{
|
||||||
StarRating = skills[0].DifficultyValue() * star_scaling_factor,
|
StarRating = skills[0].DifficultyValue() * star_scaling_factor,
|
||||||
Mods = mods,
|
Mods = mods,
|
||||||
GreatHitWindow = Math.Ceiling(getHitWindow300(mods) / clockRate),
|
// In osu-stable mania, rate-adjustment mods don't affect the hit window.
|
||||||
|
// This is done the way it is to introduce fractional differences in order to match osu-stable for the time being.
|
||||||
|
GreatHitWindow = Math.Ceiling((int)(getHitWindow300(mods) * clockRate) / clockRate),
|
||||||
ScoreMultiplier = getScoreMultiplier(mods),
|
ScoreMultiplier = getScoreMultiplier(mods),
|
||||||
MaxCombo = beatmap.HitObjects.Sum(h => h is HoldNote ? 2 : 1),
|
MaxCombo = beatmap.HitObjects.Sum(h => h is HoldNote ? 2 : 1),
|
||||||
};
|
};
|
||||||
@ -108,7 +110,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getHitWindow300(Mod[] mods)
|
private double getHitWindow300(Mod[] mods)
|
||||||
{
|
{
|
||||||
if (isForCurrentRuleset)
|
if (isForCurrentRuleset)
|
||||||
{
|
{
|
||||||
@ -121,19 +123,14 @@ namespace osu.Game.Rulesets.Mania.Difficulty
|
|||||||
|
|
||||||
return applyModAdjustments(47, mods);
|
return applyModAdjustments(47, mods);
|
||||||
|
|
||||||
static int applyModAdjustments(double value, Mod[] mods)
|
static double applyModAdjustments(double value, Mod[] mods)
|
||||||
{
|
{
|
||||||
if (mods.Any(m => m is ManiaModHardRock))
|
if (mods.Any(m => m is ManiaModHardRock))
|
||||||
value /= 1.4;
|
value /= 1.4;
|
||||||
else if (mods.Any(m => m is ManiaModEasy))
|
else if (mods.Any(m => m is ManiaModEasy))
|
||||||
value *= 1.4;
|
value *= 1.4;
|
||||||
|
|
||||||
if (mods.Any(m => m is ManiaModDoubleTime))
|
return value;
|
||||||
value *= 1.5;
|
|
||||||
else if (mods.Any(m => m is ManiaModHalfTime))
|
|
||||||
value *= 0.75;
|
|
||||||
|
|
||||||
return (int)value;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,14 +43,11 @@ namespace osu.Game.Rulesets.Mania.Difficulty
|
|||||||
countMeh = Score.Statistics.GetValueOrDefault(HitResult.Meh);
|
countMeh = Score.Statistics.GetValueOrDefault(HitResult.Meh);
|
||||||
countMiss = Score.Statistics.GetValueOrDefault(HitResult.Miss);
|
countMiss = Score.Statistics.GetValueOrDefault(HitResult.Miss);
|
||||||
|
|
||||||
IEnumerable<Mod> scoreIncreaseMods = Ruleset.GetModsFor(ModType.DifficultyIncrease);
|
if (Attributes.ScoreMultiplier > 0)
|
||||||
|
{
|
||||||
double scoreMultiplier = 1.0;
|
// Scale score up, so it's comparable to other keymods
|
||||||
foreach (var m in mods.Where(m => !scoreIncreaseMods.Contains(m)))
|
scaledScore *= 1.0 / Attributes.ScoreMultiplier;
|
||||||
scoreMultiplier *= m.ScoreMultiplier;
|
}
|
||||||
|
|
||||||
// Scale score up, so it's comparable to other keymods
|
|
||||||
scaledScore *= 1.0 / scoreMultiplier;
|
|
||||||
|
|
||||||
// Arbitrary initial value for scaling pp in order to standardize distributions across game modes.
|
// Arbitrary initial value for scaling pp in order to standardize distributions across game modes.
|
||||||
// The specific number has no intrinsic meaning and can be adjusted as needed.
|
// The specific number has no intrinsic meaning and can be adjusted as needed.
|
||||||
|
@ -98,8 +98,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
|||||||
float rightLineWidth = skin.GetManiaSkinConfig<float>(LegacyManiaSkinConfigurationLookups.RightLineWidth, columnIndex)?.Value ?? 1;
|
float rightLineWidth = skin.GetManiaSkinConfig<float>(LegacyManiaSkinConfigurationLookups.RightLineWidth, columnIndex)?.Value ?? 1;
|
||||||
|
|
||||||
bool hasLeftLine = leftLineWidth > 0;
|
bool hasLeftLine = leftLineWidth > 0;
|
||||||
bool hasRightLine = rightLineWidth > 0 && skin.GetConfig<SkinConfiguration.LegacySetting, decimal>(SkinConfiguration.LegacySetting.Version)?.Value >= 2.4m
|
bool hasRightLine = (rightLineWidth > 0 && skin.GetConfig<SkinConfiguration.LegacySetting, decimal>(SkinConfiguration.LegacySetting.Version)?.Value >= 2.4m) || isLastColumn;
|
||||||
|| isLastColumn;
|
|
||||||
|
|
||||||
Color4 lineColour = skin.GetManiaSkinConfig<Color4>(LegacyManiaSkinConfigurationLookups.ColumnLineColour, columnIndex)?.Value ?? Color4.White;
|
Color4 lineColour = skin.GetManiaSkinConfig<Color4>(LegacyManiaSkinConfigurationLookups.ColumnLineColour, columnIndex)?.Value ?? Color4.White;
|
||||||
Color4 backgroundColour = skin.GetManiaSkinConfig<Color4>(LegacyManiaSkinConfigurationLookups.ColumnBackgroundColour, columnIndex)?.Value ?? Color4.Black;
|
Color4 backgroundColour = skin.GetManiaSkinConfig<Color4>(LegacyManiaSkinConfigurationLookups.ColumnBackgroundColour, columnIndex)?.Value ?? Color4.Black;
|
||||||
|
@ -10,9 +10,9 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Label="Project References">
|
<ItemGroup Label="Project References">
|
||||||
<ProjectReference Include="..\osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj" />
|
<ProjectReference Include="..\osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -12,30 +12,68 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
|||||||
{
|
{
|
||||||
public class OsuDifficultyAttributes : DifficultyAttributes
|
public class OsuDifficultyAttributes : DifficultyAttributes
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The difficulty corresponding to the aim skill.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("aim_difficulty")]
|
[JsonProperty("aim_difficulty")]
|
||||||
public double AimDifficulty { get; set; }
|
public double AimDifficulty { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The difficulty corresponding to the speed skill.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("speed_difficulty")]
|
[JsonProperty("speed_difficulty")]
|
||||||
public double SpeedDifficulty { get; set; }
|
public double SpeedDifficulty { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The difficulty corresponding to the flashlight skill.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("flashlight_difficulty")]
|
[JsonProperty("flashlight_difficulty")]
|
||||||
public double FlashlightDifficulty { get; set; }
|
public double FlashlightDifficulty { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Describes how much of <see cref="AimDifficulty"/> is contributed to by hitcircles or sliders.
|
||||||
|
/// A value closer to 1.0 indicates most of <see cref="AimDifficulty"/> is contributed by hitcircles.
|
||||||
|
/// A value closer to 0.0 indicates most of <see cref="AimDifficulty"/> is contributed by sliders.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("slider_factor")]
|
[JsonProperty("slider_factor")]
|
||||||
public double SliderFactor { get; set; }
|
public double SliderFactor { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The perceived approach rate inclusive of rate-adjusting mods (DT/HT/etc).
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Rate-adjusting mods don't directly affect the approach rate difficulty value, but have a perceived effect as a result of adjusting audio timing.
|
||||||
|
/// </remarks>
|
||||||
[JsonProperty("approach_rate")]
|
[JsonProperty("approach_rate")]
|
||||||
public double ApproachRate { get; set; }
|
public double ApproachRate { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The perceived overall difficulty inclusive of rate-adjusting mods (DT/HT/etc).
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Rate-adjusting mods don't directly affect the overall difficulty value, but have a perceived effect as a result of adjusting audio timing.
|
||||||
|
/// </remarks>
|
||||||
[JsonProperty("overall_difficulty")]
|
[JsonProperty("overall_difficulty")]
|
||||||
public double OverallDifficulty { get; set; }
|
public double OverallDifficulty { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The beatmap's drain rate. This doesn't scale with rate-adjusting mods.
|
||||||
|
/// </summary>
|
||||||
public double DrainRate { get; set; }
|
public double DrainRate { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The number of hitcircles in the beatmap.
|
||||||
|
/// </summary>
|
||||||
public int HitCircleCount { get; set; }
|
public int HitCircleCount { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The number of sliders in the beatmap.
|
||||||
|
/// </summary>
|
||||||
public int SliderCount { get; set; }
|
public int SliderCount { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The number of spinners in the beatmap.
|
||||||
|
/// </summary>
|
||||||
public int SpinnerCount { get; set; }
|
public int SpinnerCount { get; set; }
|
||||||
|
|
||||||
public override IEnumerable<(int attributeId, object value)> ToDatabaseAttributes()
|
public override IEnumerable<(int attributeId, object value)> ToDatabaseAttributes()
|
||||||
|
@ -87,8 +87,8 @@ namespace osu.Game.Rulesets.Osu.Mods
|
|||||||
requiresHold |= slider.Ball.IsHovered || h.IsHovered;
|
requiresHold |= slider.Ball.IsHovered || h.IsHovered;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DrawableSpinner _:
|
case DrawableSpinner spinner:
|
||||||
requiresHold = true;
|
requiresHold |= spinner.HitObject.SpinsRequired > 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,9 +9,9 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Label="Project References">
|
<ItemGroup Label="Project References">
|
||||||
<ProjectReference Include="..\osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj" />
|
<ProjectReference Include="..\osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -9,18 +9,39 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
|
|||||||
{
|
{
|
||||||
public class TaikoDifficultyAttributes : DifficultyAttributes
|
public class TaikoDifficultyAttributes : DifficultyAttributes
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The difficulty corresponding to the stamina skill.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("stamina_difficulty")]
|
[JsonProperty("stamina_difficulty")]
|
||||||
public double StaminaDifficulty { get; set; }
|
public double StaminaDifficulty { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The difficulty corresponding to the rhythm skill.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("rhythm_difficulty")]
|
[JsonProperty("rhythm_difficulty")]
|
||||||
public double RhythmDifficulty { get; set; }
|
public double RhythmDifficulty { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The difficulty corresponding to the colour skill.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("colour_difficulty")]
|
[JsonProperty("colour_difficulty")]
|
||||||
public double ColourDifficulty { get; set; }
|
public double ColourDifficulty { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The perceived approach rate inclusive of rate-adjusting mods (DT/HT/etc).
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Rate-adjusting mods don't directly affect the approach rate difficulty value, but have a perceived effect as a result of adjusting audio timing.
|
||||||
|
/// </remarks>
|
||||||
[JsonProperty("approach_rate")]
|
[JsonProperty("approach_rate")]
|
||||||
public double ApproachRate { get; set; }
|
public double ApproachRate { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The perceived hit window for a GREAT hit inclusive of rate-adjusting mods (DT/HT/etc).
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Rate-adjusting mods don't directly affect the hit window, but have a perceived effect as a result of adjusting audio timing.
|
||||||
|
/// </remarks>
|
||||||
[JsonProperty("great_hit_window")]
|
[JsonProperty("great_hit_window")]
|
||||||
public double GreatHitWindow { get; set; }
|
public double GreatHitWindow { get; set; }
|
||||||
|
|
||||||
|
@ -21,8 +21,8 @@ namespace osu.Game.Tests.NonVisual.Multiplayer
|
|||||||
{
|
{
|
||||||
var user = new APIUser { Id = 33 };
|
var user = new APIUser { Id = 33 };
|
||||||
|
|
||||||
AddRepeatStep("add user multiple times", () => Client.AddUser(user), 3);
|
AddRepeatStep("add user multiple times", () => MultiplayerClient.AddUser(user), 3);
|
||||||
AddAssert("room has 2 users", () => Client.Room?.Users.Count == 2);
|
AddAssert("room has 2 users", () => MultiplayerClient.Room?.Users.Count == 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -30,11 +30,11 @@ namespace osu.Game.Tests.NonVisual.Multiplayer
|
|||||||
{
|
{
|
||||||
var user = new APIUser { Id = 44 };
|
var user = new APIUser { Id = 44 };
|
||||||
|
|
||||||
AddStep("add user", () => Client.AddUser(user));
|
AddStep("add user", () => MultiplayerClient.AddUser(user));
|
||||||
AddAssert("room has 2 users", () => Client.Room?.Users.Count == 2);
|
AddAssert("room has 2 users", () => MultiplayerClient.Room?.Users.Count == 2);
|
||||||
|
|
||||||
AddRepeatStep("remove user multiple times", () => Client.RemoveUser(user), 3);
|
AddRepeatStep("remove user multiple times", () => MultiplayerClient.RemoveUser(user), 3);
|
||||||
AddAssert("room has 1 user", () => Client.Room?.Users.Count == 1);
|
AddAssert("room has 1 user", () => MultiplayerClient.Room?.Users.Count == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -42,7 +42,7 @@ namespace osu.Game.Tests.NonVisual.Multiplayer
|
|||||||
{
|
{
|
||||||
int id = 2000;
|
int id = 2000;
|
||||||
|
|
||||||
AddRepeatStep("add some users", () => Client.AddUser(new APIUser { Id = id++ }), 5);
|
AddRepeatStep("add some users", () => MultiplayerClient.AddUser(new APIUser { Id = id++ }), 5);
|
||||||
checkPlayingUserCount(0);
|
checkPlayingUserCount(0);
|
||||||
|
|
||||||
changeState(3, MultiplayerUserState.WaitingForLoad);
|
changeState(3, MultiplayerUserState.WaitingForLoad);
|
||||||
@ -57,17 +57,17 @@ namespace osu.Game.Tests.NonVisual.Multiplayer
|
|||||||
changeState(6, MultiplayerUserState.WaitingForLoad);
|
changeState(6, MultiplayerUserState.WaitingForLoad);
|
||||||
checkPlayingUserCount(6);
|
checkPlayingUserCount(6);
|
||||||
|
|
||||||
AddStep("another user left", () => Client.RemoveUser((Client.Room?.Users.Last().User).AsNonNull()));
|
AddStep("another user left", () => MultiplayerClient.RemoveUser((MultiplayerClient.Room?.Users.Last().User).AsNonNull()));
|
||||||
checkPlayingUserCount(5);
|
checkPlayingUserCount(5);
|
||||||
|
|
||||||
AddStep("leave room", () => Client.LeaveRoom());
|
AddStep("leave room", () => MultiplayerClient.LeaveRoom());
|
||||||
checkPlayingUserCount(0);
|
checkPlayingUserCount(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestPlayingUsersUpdatedOnJoin()
|
public void TestPlayingUsersUpdatedOnJoin()
|
||||||
{
|
{
|
||||||
AddStep("leave room", () => Client.LeaveRoom());
|
AddStep("leave room", () => MultiplayerClient.LeaveRoom());
|
||||||
AddUntilStep("wait for room part", () => !RoomJoined);
|
AddUntilStep("wait for room part", () => !RoomJoined);
|
||||||
|
|
||||||
AddStep("create room initially in gameplay", () =>
|
AddStep("create room initially in gameplay", () =>
|
||||||
@ -76,7 +76,7 @@ namespace osu.Game.Tests.NonVisual.Multiplayer
|
|||||||
newRoom.CopyFrom(SelectedRoom.Value);
|
newRoom.CopyFrom(SelectedRoom.Value);
|
||||||
|
|
||||||
newRoom.RoomID.Value = null;
|
newRoom.RoomID.Value = null;
|
||||||
Client.RoomSetupAction = room =>
|
MultiplayerClient.RoomSetupAction = room =>
|
||||||
{
|
{
|
||||||
room.State = MultiplayerRoomState.Playing;
|
room.State = MultiplayerRoomState.Playing;
|
||||||
room.Users.Add(new MultiplayerRoomUser(PLAYER_1_ID)
|
room.Users.Add(new MultiplayerRoomUser(PLAYER_1_ID)
|
||||||
@ -94,15 +94,15 @@ namespace osu.Game.Tests.NonVisual.Multiplayer
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void checkPlayingUserCount(int expectedCount)
|
private void checkPlayingUserCount(int expectedCount)
|
||||||
=> AddAssert($"{"user".ToQuantity(expectedCount)} playing", () => Client.CurrentMatchPlayingUserIds.Count == expectedCount);
|
=> AddAssert($"{"user".ToQuantity(expectedCount)} playing", () => MultiplayerClient.CurrentMatchPlayingUserIds.Count == expectedCount);
|
||||||
|
|
||||||
private void changeState(int userCount, MultiplayerUserState state)
|
private void changeState(int userCount, MultiplayerUserState state)
|
||||||
=> AddStep($"{"user".ToQuantity(userCount)} in {state}", () =>
|
=> AddStep($"{"user".ToQuantity(userCount)} in {state}", () =>
|
||||||
{
|
{
|
||||||
for (int i = 0; i < userCount; ++i)
|
for (int i = 0; i < userCount; ++i)
|
||||||
{
|
{
|
||||||
int userId = Client.Room?.Users[i].UserID ?? throw new AssertionException("Room cannot be null!");
|
int userId = MultiplayerClient.Room?.Users[i].UserID ?? throw new AssertionException("Room cannot be null!");
|
||||||
Client.ChangeUserState(userId, state);
|
MultiplayerClient.ChangeUserState(userId, state);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@ -12,6 +13,7 @@ using osu.Framework.Allocation;
|
|||||||
using osu.Framework.Audio;
|
using osu.Framework.Audio;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Extensions;
|
using osu.Framework.Extensions;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.IO.Stores;
|
using osu.Framework.IO.Stores;
|
||||||
using osu.Framework.Platform;
|
using osu.Framework.Platform;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
@ -21,6 +23,8 @@ using osu.Game.Database;
|
|||||||
using osu.Game.IO;
|
using osu.Game.IO;
|
||||||
using osu.Game.IO.Archives;
|
using osu.Game.IO.Archives;
|
||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
|
using osu.Game.Online.API.Requests;
|
||||||
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
using osu.Game.Online.Rooms;
|
using osu.Game.Online.Rooms;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Tests.Resources;
|
using osu.Game.Tests.Resources;
|
||||||
@ -53,6 +57,25 @@ namespace osu.Game.Tests.Online
|
|||||||
[SetUp]
|
[SetUp]
|
||||||
public void SetUp() => Schedule(() =>
|
public void SetUp() => Schedule(() =>
|
||||||
{
|
{
|
||||||
|
((DummyAPIAccess)API).HandleRequest = req =>
|
||||||
|
{
|
||||||
|
switch (req)
|
||||||
|
{
|
||||||
|
case GetBeatmapsRequest beatmapsReq:
|
||||||
|
var beatmap = CreateAPIBeatmap();
|
||||||
|
beatmap.OnlineID = testBeatmapInfo.OnlineID;
|
||||||
|
beatmap.OnlineBeatmapSetID = testBeatmapSet.OnlineID;
|
||||||
|
beatmap.Checksum = testBeatmapInfo.MD5Hash;
|
||||||
|
beatmap.BeatmapSet!.OnlineID = testBeatmapSet.OnlineID;
|
||||||
|
|
||||||
|
beatmapsReq.TriggerSuccess(new GetBeatmapsResponse { Beatmaps = new List<APIBeatmap> { beatmap } });
|
||||||
|
return true;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
beatmaps.AllowImport = new TaskCompletionSource<bool>();
|
beatmaps.AllowImport = new TaskCompletionSource<bool>();
|
||||||
|
|
||||||
testBeatmapFile = TestResources.GetQuickTestBeatmapForImport();
|
testBeatmapFile = TestResources.GetQuickTestBeatmapForImport();
|
||||||
@ -63,18 +86,35 @@ namespace osu.Game.Tests.Online
|
|||||||
Realm.Write(r => r.RemoveAll<BeatmapSetInfo>());
|
Realm.Write(r => r.RemoveAll<BeatmapSetInfo>());
|
||||||
Realm.Write(r => r.RemoveAll<BeatmapInfo>());
|
Realm.Write(r => r.RemoveAll<BeatmapInfo>());
|
||||||
|
|
||||||
selectedItem.Value = new PlaylistItem
|
selectedItem.Value = new PlaylistItem(testBeatmapInfo)
|
||||||
{
|
{
|
||||||
Beatmap = { Value = testBeatmapInfo },
|
RulesetID = testBeatmapInfo.Ruleset.OnlineID,
|
||||||
Ruleset = { Value = testBeatmapInfo.Ruleset },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Child = availabilityTracker = new OnlinePlayBeatmapAvailabilityTracker
|
recreateChildren();
|
||||||
{
|
|
||||||
SelectedItem = { BindTarget = selectedItem, }
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
private void recreateChildren()
|
||||||
|
{
|
||||||
|
var beatmapLookupCache = new BeatmapLookupCache();
|
||||||
|
|
||||||
|
Child = new DependencyProvidingContainer
|
||||||
|
{
|
||||||
|
CachedDependencies = new[]
|
||||||
|
{
|
||||||
|
(typeof(BeatmapLookupCache), (object)beatmapLookupCache)
|
||||||
|
},
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
beatmapLookupCache,
|
||||||
|
availabilityTracker = new OnlinePlayBeatmapAvailabilityTracker
|
||||||
|
{
|
||||||
|
SelectedItem = { BindTarget = selectedItem, }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestBeatmapDownloadingFlow()
|
public void TestBeatmapDownloadingFlow()
|
||||||
{
|
{
|
||||||
@ -123,10 +163,7 @@ namespace osu.Game.Tests.Online
|
|||||||
});
|
});
|
||||||
addAvailabilityCheckStep("state not downloaded", BeatmapAvailability.NotDownloaded);
|
addAvailabilityCheckStep("state not downloaded", BeatmapAvailability.NotDownloaded);
|
||||||
|
|
||||||
AddStep("recreate tracker", () => Child = availabilityTracker = new OnlinePlayBeatmapAvailabilityTracker
|
AddStep("recreate tracker", recreateChildren);
|
||||||
{
|
|
||||||
SelectedItem = { BindTarget = selectedItem }
|
|
||||||
});
|
|
||||||
addAvailabilityCheckStep("state not downloaded as well", BeatmapAvailability.NotDownloaded);
|
addAvailabilityCheckStep("state not downloaded as well", BeatmapAvailability.NotDownloaded);
|
||||||
|
|
||||||
AddStep("reimport original beatmap", () => beatmaps.Import(TestResources.GetQuickTestBeatmapForImport()).WaitSafely());
|
AddStep("reimport original beatmap", () => beatmaps.Import(TestResources.GetQuickTestBeatmapForImport()).WaitSafely());
|
||||||
@ -167,7 +204,8 @@ namespace osu.Game.Tests.Online
|
|||||||
|
|
||||||
public Live<BeatmapSetInfo> CurrentImport { get; private set; }
|
public Live<BeatmapSetInfo> CurrentImport { get; private set; }
|
||||||
|
|
||||||
public TestBeatmapManager(Storage storage, RealmAccess realm, RulesetStore rulesets, IAPIProvider api, [NotNull] AudioManager audioManager, IResourceStore<byte[]> resources, GameHost host = null, WorkingBeatmap defaultBeatmap = null)
|
public TestBeatmapManager(Storage storage, RealmAccess realm, RulesetStore rulesets, IAPIProvider api, [NotNull] AudioManager audioManager, IResourceStore<byte[]> resources,
|
||||||
|
GameHost host = null, WorkingBeatmap defaultBeatmap = null)
|
||||||
: base(storage, realm, rulesets, api, audioManager, resources, host, defaultBeatmap)
|
: base(storage, realm, rulesets, api, audioManager, resources, host, defaultBeatmap)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
using osu.Game.Online.Rooms;
|
using osu.Game.Online.Rooms;
|
||||||
|
|
||||||
namespace osu.Game.Tests.OnlinePlay
|
namespace osu.Game.Tests.OnlinePlay
|
||||||
@ -29,9 +30,9 @@ namespace osu.Game.Tests.OnlinePlay
|
|||||||
{
|
{
|
||||||
var items = new[]
|
var items = new[]
|
||||||
{
|
{
|
||||||
new PlaylistItem { ID = 1, BeatmapID = 1001, PlaylistOrder = 1 },
|
new PlaylistItem(new APIBeatmap { OnlineID = 1001 }) { ID = 1, PlaylistOrder = 1 },
|
||||||
new PlaylistItem { ID = 2, BeatmapID = 1002, PlaylistOrder = 2 },
|
new PlaylistItem(new APIBeatmap { OnlineID = 1002 }) { ID = 2, PlaylistOrder = 2 },
|
||||||
new PlaylistItem { ID = 3, BeatmapID = 1003, PlaylistOrder = 3 },
|
new PlaylistItem(new APIBeatmap { OnlineID = 1003 }) { ID = 3, PlaylistOrder = 3 },
|
||||||
};
|
};
|
||||||
|
|
||||||
Assert.Multiple(() =>
|
Assert.Multiple(() =>
|
||||||
@ -47,9 +48,9 @@ namespace osu.Game.Tests.OnlinePlay
|
|||||||
{
|
{
|
||||||
var items = new[]
|
var items = new[]
|
||||||
{
|
{
|
||||||
new PlaylistItem { ID = 2, BeatmapID = 1002, PlaylistOrder = 2 },
|
new PlaylistItem(new APIBeatmap { OnlineID = 1002 }) { ID = 2, PlaylistOrder = 2 },
|
||||||
new PlaylistItem { ID = 1, BeatmapID = 1001, PlaylistOrder = 1 },
|
new PlaylistItem(new APIBeatmap { OnlineID = 1001 }) { ID = 1, PlaylistOrder = 1 },
|
||||||
new PlaylistItem { ID = 3, BeatmapID = 1003, PlaylistOrder = 3 },
|
new PlaylistItem(new APIBeatmap { OnlineID = 1003 }) { ID = 3, PlaylistOrder = 3 },
|
||||||
};
|
};
|
||||||
|
|
||||||
Assert.Multiple(() =>
|
Assert.Multiple(() =>
|
||||||
@ -65,9 +66,9 @@ namespace osu.Game.Tests.OnlinePlay
|
|||||||
{
|
{
|
||||||
var items = new[]
|
var items = new[]
|
||||||
{
|
{
|
||||||
new PlaylistItem { ID = 1, BeatmapID = 1001, Expired = true, PlayedAt = new DateTimeOffset(2021, 12, 21, 7, 55, 0, TimeSpan.Zero) },
|
new PlaylistItem(new APIBeatmap { OnlineID = 1001 }) { ID = 1, Expired = true, PlayedAt = new DateTimeOffset(2021, 12, 21, 7, 55, 0, TimeSpan.Zero) },
|
||||||
new PlaylistItem { ID = 2, BeatmapID = 1002, Expired = true, PlayedAt = new DateTimeOffset(2021, 12, 21, 7, 53, 0, TimeSpan.Zero) },
|
new PlaylistItem(new APIBeatmap { OnlineID = 1002 }) { ID = 2, Expired = true, PlayedAt = new DateTimeOffset(2021, 12, 21, 7, 53, 0, TimeSpan.Zero) },
|
||||||
new PlaylistItem { ID = 3, BeatmapID = 1003, PlaylistOrder = 3 },
|
new PlaylistItem(new APIBeatmap { OnlineID = 1003 }) { ID = 3, PlaylistOrder = 3 },
|
||||||
};
|
};
|
||||||
|
|
||||||
Assert.Multiple(() =>
|
Assert.Multiple(() =>
|
||||||
@ -83,9 +84,9 @@ namespace osu.Game.Tests.OnlinePlay
|
|||||||
{
|
{
|
||||||
var items = new[]
|
var items = new[]
|
||||||
{
|
{
|
||||||
new PlaylistItem { ID = 1, BeatmapID = 1001, Expired = true, PlayedAt = new DateTimeOffset(2021, 12, 21, 7, 55, 0, TimeSpan.Zero) },
|
new PlaylistItem(new APIBeatmap { OnlineID = 1001 }) { ID = 1, Expired = true, PlayedAt = new DateTimeOffset(2021, 12, 21, 7, 55, 0, TimeSpan.Zero) },
|
||||||
new PlaylistItem { ID = 2, BeatmapID = 1002, Expired = true, PlayedAt = new DateTimeOffset(2021, 12, 21, 7, 53, 0, TimeSpan.Zero) },
|
new PlaylistItem(new APIBeatmap { OnlineID = 1002 }) { ID = 2, Expired = true, PlayedAt = new DateTimeOffset(2021, 12, 21, 7, 53, 0, TimeSpan.Zero) },
|
||||||
new PlaylistItem { ID = 3, BeatmapID = 1002, Expired = true, PlayedAt = new DateTimeOffset(2021, 12, 21, 7, 57, 0, TimeSpan.Zero) },
|
new PlaylistItem(new APIBeatmap { OnlineID = 1002 }) { ID = 3, Expired = true, PlayedAt = new DateTimeOffset(2021, 12, 21, 7, 57, 0, TimeSpan.Zero) },
|
||||||
};
|
};
|
||||||
|
|
||||||
Assert.Multiple(() =>
|
Assert.Multiple(() =>
|
||||||
|
BIN
osu.Game.Tests/Resources/client.db
Normal file
BIN
osu.Game.Tests/Resources/client.db
Normal file
Binary file not shown.
@ -36,9 +36,9 @@ namespace osu.Game.Tests.Rulesets.Scoring
|
|||||||
[TestCase(ScoringMode.Standardised, HitResult.Meh, 750_000)]
|
[TestCase(ScoringMode.Standardised, HitResult.Meh, 750_000)]
|
||||||
[TestCase(ScoringMode.Standardised, HitResult.Ok, 800_000)]
|
[TestCase(ScoringMode.Standardised, HitResult.Ok, 800_000)]
|
||||||
[TestCase(ScoringMode.Standardised, HitResult.Great, 1_000_000)]
|
[TestCase(ScoringMode.Standardised, HitResult.Great, 1_000_000)]
|
||||||
[TestCase(ScoringMode.Classic, HitResult.Meh, 41)]
|
[TestCase(ScoringMode.Classic, HitResult.Meh, 20)]
|
||||||
[TestCase(ScoringMode.Classic, HitResult.Ok, 46)]
|
[TestCase(ScoringMode.Classic, HitResult.Ok, 23)]
|
||||||
[TestCase(ScoringMode.Classic, HitResult.Great, 72)]
|
[TestCase(ScoringMode.Classic, HitResult.Great, 36)]
|
||||||
public void TestSingleOsuHit(ScoringMode scoringMode, HitResult hitResult, int expectedScore)
|
public void TestSingleOsuHit(ScoringMode scoringMode, HitResult hitResult, int expectedScore)
|
||||||
{
|
{
|
||||||
scoreProcessor.Mode.Value = scoringMode;
|
scoreProcessor.Mode.Value = scoringMode;
|
||||||
@ -86,17 +86,17 @@ namespace osu.Game.Tests.Rulesets.Scoring
|
|||||||
[TestCase(ScoringMode.Standardised, HitResult.SmallBonus, HitResult.SmallBonus, 1_000_030)] // 1 * 300_000 + 700_000 (max combo 0) + 3 * 10 (bonus points)
|
[TestCase(ScoringMode.Standardised, HitResult.SmallBonus, HitResult.SmallBonus, 1_000_030)] // 1 * 300_000 + 700_000 (max combo 0) + 3 * 10 (bonus points)
|
||||||
[TestCase(ScoringMode.Standardised, HitResult.LargeBonus, HitResult.LargeBonus, 1_000_150)] // 1 * 300_000 + 700_000 (max combo 0) + 3 * 50 (bonus points)
|
[TestCase(ScoringMode.Standardised, HitResult.LargeBonus, HitResult.LargeBonus, 1_000_150)] // 1 * 300_000 + 700_000 (max combo 0) + 3 * 50 (bonus points)
|
||||||
[TestCase(ScoringMode.Classic, HitResult.Miss, HitResult.Great, 0)]
|
[TestCase(ScoringMode.Classic, HitResult.Miss, HitResult.Great, 0)]
|
||||||
[TestCase(ScoringMode.Classic, HitResult.Meh, HitResult.Great, 68)]
|
[TestCase(ScoringMode.Classic, HitResult.Meh, HitResult.Great, 86)]
|
||||||
[TestCase(ScoringMode.Classic, HitResult.Ok, HitResult.Great, 81)]
|
[TestCase(ScoringMode.Classic, HitResult.Ok, HitResult.Great, 104)]
|
||||||
[TestCase(ScoringMode.Classic, HitResult.Good, HitResult.Perfect, 109)]
|
[TestCase(ScoringMode.Classic, HitResult.Good, HitResult.Perfect, 140)]
|
||||||
[TestCase(ScoringMode.Classic, HitResult.Great, HitResult.Great, 149)]
|
[TestCase(ScoringMode.Classic, HitResult.Great, HitResult.Great, 190)]
|
||||||
[TestCase(ScoringMode.Classic, HitResult.Perfect, HitResult.Perfect, 149)]
|
[TestCase(ScoringMode.Classic, HitResult.Perfect, HitResult.Perfect, 190)]
|
||||||
[TestCase(ScoringMode.Classic, HitResult.SmallTickMiss, HitResult.SmallTickHit, 9)]
|
[TestCase(ScoringMode.Classic, HitResult.SmallTickMiss, HitResult.SmallTickHit, 18)]
|
||||||
[TestCase(ScoringMode.Classic, HitResult.SmallTickHit, HitResult.SmallTickHit, 15)]
|
[TestCase(ScoringMode.Classic, HitResult.SmallTickHit, HitResult.SmallTickHit, 31)]
|
||||||
[TestCase(ScoringMode.Classic, HitResult.LargeTickMiss, HitResult.LargeTickHit, 0)]
|
[TestCase(ScoringMode.Classic, HitResult.LargeTickMiss, HitResult.LargeTickHit, 0)]
|
||||||
[TestCase(ScoringMode.Classic, HitResult.LargeTickHit, HitResult.LargeTickHit, 149)]
|
[TestCase(ScoringMode.Classic, HitResult.LargeTickHit, HitResult.LargeTickHit, 12)]
|
||||||
[TestCase(ScoringMode.Classic, HitResult.SmallBonus, HitResult.SmallBonus, 18)]
|
[TestCase(ScoringMode.Classic, HitResult.SmallBonus, HitResult.SmallBonus, 36)]
|
||||||
[TestCase(ScoringMode.Classic, HitResult.LargeBonus, HitResult.LargeBonus, 18)]
|
[TestCase(ScoringMode.Classic, HitResult.LargeBonus, HitResult.LargeBonus, 36)]
|
||||||
public void TestFourVariousResultsOneMiss(ScoringMode scoringMode, HitResult hitResult, HitResult maxResult, int expectedScore)
|
public void TestFourVariousResultsOneMiss(ScoringMode scoringMode, HitResult hitResult, HitResult maxResult, int expectedScore)
|
||||||
{
|
{
|
||||||
var minResult = new TestJudgement(hitResult).MinResult;
|
var minResult = new TestJudgement(hitResult).MinResult;
|
||||||
@ -128,8 +128,8 @@ namespace osu.Game.Tests.Rulesets.Scoring
|
|||||||
/// </remarks>
|
/// </remarks>
|
||||||
[TestCase(ScoringMode.Standardised, HitResult.SmallTickHit, 978_571)] // (3 * 10 + 100) / (4 * 10 + 100) * 300_000 + (1 / 1) * 700_000
|
[TestCase(ScoringMode.Standardised, HitResult.SmallTickHit, 978_571)] // (3 * 10 + 100) / (4 * 10 + 100) * 300_000 + (1 / 1) * 700_000
|
||||||
[TestCase(ScoringMode.Standardised, HitResult.SmallTickMiss, 914_286)] // (3 * 0 + 100) / (4 * 10 + 100) * 300_000 + (1 / 1) * 700_000
|
[TestCase(ScoringMode.Standardised, HitResult.SmallTickMiss, 914_286)] // (3 * 0 + 100) / (4 * 10 + 100) * 300_000 + (1 / 1) * 700_000
|
||||||
[TestCase(ScoringMode.Classic, HitResult.SmallTickHit, 69)] // (((3 * 10 + 100) / (4 * 10 + 100)) * 1 * 300) * (1 + 0 / 25)
|
[TestCase(ScoringMode.Classic, HitResult.SmallTickHit, 34)]
|
||||||
[TestCase(ScoringMode.Classic, HitResult.SmallTickMiss, 60)] // (((3 * 0 + 100) / (4 * 10 + 100)) * 1 * 300) * (1 + 0 / 25)
|
[TestCase(ScoringMode.Classic, HitResult.SmallTickMiss, 30)]
|
||||||
public void TestSmallTicksAccuracy(ScoringMode scoringMode, HitResult hitResult, int expectedScore)
|
public void TestSmallTicksAccuracy(ScoringMode scoringMode, HitResult hitResult, int expectedScore)
|
||||||
{
|
{
|
||||||
IEnumerable<HitObject> hitObjects = Enumerable
|
IEnumerable<HitObject> hitObjects = Enumerable
|
||||||
|
132
osu.Game.Tests/Utils/NamingUtilsTest.cs
Normal file
132
osu.Game.Tests/Utils/NamingUtilsTest.cs
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System.Linq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Game.Utils;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Utils
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class NamingUtilsTest
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void TestEmptySet()
|
||||||
|
{
|
||||||
|
string nextBestName = NamingUtils.GetNextBestName(Enumerable.Empty<string>(), "New Difficulty");
|
||||||
|
|
||||||
|
Assert.AreEqual("New Difficulty", nextBestName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestNotTaken()
|
||||||
|
{
|
||||||
|
string[] existingNames =
|
||||||
|
{
|
||||||
|
"Something",
|
||||||
|
"Entirely",
|
||||||
|
"Different"
|
||||||
|
};
|
||||||
|
|
||||||
|
string nextBestName = NamingUtils.GetNextBestName(existingNames, "New Difficulty");
|
||||||
|
|
||||||
|
Assert.AreEqual("New Difficulty", nextBestName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestNotTakenButClose()
|
||||||
|
{
|
||||||
|
string[] existingNames =
|
||||||
|
{
|
||||||
|
"New Difficulty(1)",
|
||||||
|
"New Difficulty (abcd)",
|
||||||
|
"New Difficulty but not really"
|
||||||
|
};
|
||||||
|
|
||||||
|
string nextBestName = NamingUtils.GetNextBestName(existingNames, "New Difficulty");
|
||||||
|
|
||||||
|
Assert.AreEqual("New Difficulty", nextBestName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestAlreadyTaken()
|
||||||
|
{
|
||||||
|
string[] existingNames =
|
||||||
|
{
|
||||||
|
"New Difficulty"
|
||||||
|
};
|
||||||
|
|
||||||
|
string nextBestName = NamingUtils.GetNextBestName(existingNames, "New Difficulty");
|
||||||
|
|
||||||
|
Assert.AreEqual("New Difficulty (1)", nextBestName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestAlreadyTakenWithDifferentCase()
|
||||||
|
{
|
||||||
|
string[] existingNames =
|
||||||
|
{
|
||||||
|
"new difficulty"
|
||||||
|
};
|
||||||
|
|
||||||
|
string nextBestName = NamingUtils.GetNextBestName(existingNames, "New Difficulty");
|
||||||
|
|
||||||
|
Assert.AreEqual("New Difficulty (1)", nextBestName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestAlreadyTakenWithBrackets()
|
||||||
|
{
|
||||||
|
string[] existingNames =
|
||||||
|
{
|
||||||
|
"new difficulty (copy)"
|
||||||
|
};
|
||||||
|
|
||||||
|
string nextBestName = NamingUtils.GetNextBestName(existingNames, "New Difficulty (copy)");
|
||||||
|
|
||||||
|
Assert.AreEqual("New Difficulty (copy) (1)", nextBestName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestMultipleAlreadyTaken()
|
||||||
|
{
|
||||||
|
string[] existingNames =
|
||||||
|
{
|
||||||
|
"New Difficulty",
|
||||||
|
"New difficulty (1)",
|
||||||
|
"new Difficulty (2)",
|
||||||
|
"New DIFFICULTY (3)"
|
||||||
|
};
|
||||||
|
|
||||||
|
string nextBestName = NamingUtils.GetNextBestName(existingNames, "New Difficulty");
|
||||||
|
|
||||||
|
Assert.AreEqual("New Difficulty (4)", nextBestName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestEvenMoreAlreadyTaken()
|
||||||
|
{
|
||||||
|
string[] existingNames = Enumerable.Range(1, 30).Select(i => $"New Difficulty ({i})").Append("New Difficulty").ToArray();
|
||||||
|
|
||||||
|
string nextBestName = NamingUtils.GetNextBestName(existingNames, "New Difficulty");
|
||||||
|
|
||||||
|
Assert.AreEqual("New Difficulty (31)", nextBestName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestMultipleAlreadyTakenWithGaps()
|
||||||
|
{
|
||||||
|
string[] existingNames =
|
||||||
|
{
|
||||||
|
"New Difficulty",
|
||||||
|
"New Difficulty (1)",
|
||||||
|
"New Difficulty (4)",
|
||||||
|
"New Difficulty (9)"
|
||||||
|
};
|
||||||
|
|
||||||
|
string nextBestName = NamingUtils.GetNextBestName(existingNames, "New Difficulty");
|
||||||
|
|
||||||
|
Assert.AreEqual("New Difficulty (2)", nextBestName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -6,15 +6,23 @@ using System.IO;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Extensions.ObjectExtensions;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Screens;
|
using osu.Framework.Screens;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
|
using osu.Game.Database;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
|
using osu.Game.Rulesets.Catch;
|
||||||
using osu.Game.Rulesets.Osu;
|
using osu.Game.Rulesets.Osu;
|
||||||
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
|
using osu.Game.Rulesets.Osu.UI;
|
||||||
using osu.Game.Screens.Edit;
|
using osu.Game.Screens.Edit;
|
||||||
using osu.Game.Screens.Edit.Setup;
|
using osu.Game.Screens.Edit.Setup;
|
||||||
using osu.Game.Storyboards;
|
using osu.Game.Storyboards;
|
||||||
using osu.Game.Tests.Resources;
|
using osu.Game.Tests.Resources;
|
||||||
|
using osuTK;
|
||||||
using SharpCompress.Archives;
|
using SharpCompress.Archives;
|
||||||
using SharpCompress.Archives.Zip;
|
using SharpCompress.Archives.Zip;
|
||||||
|
|
||||||
@ -92,12 +100,27 @@ namespace osu.Game.Tests.Visual.Editing
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestCreateNewDifficulty()
|
public void TestCreateNewDifficulty([Values] bool sameRuleset)
|
||||||
{
|
{
|
||||||
string firstDifficultyName = Guid.NewGuid().ToString();
|
string firstDifficultyName = Guid.NewGuid().ToString();
|
||||||
string secondDifficultyName = Guid.NewGuid().ToString();
|
string secondDifficultyName = Guid.NewGuid().ToString();
|
||||||
|
|
||||||
AddStep("set unique difficulty name", () => EditorBeatmap.BeatmapInfo.DifficultyName = firstDifficultyName);
|
AddStep("set unique difficulty name", () => EditorBeatmap.BeatmapInfo.DifficultyName = firstDifficultyName);
|
||||||
|
AddStep("add timing point", () => EditorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = 1000 }));
|
||||||
|
AddStep("add hitobjects", () => EditorBeatmap.AddRange(new[]
|
||||||
|
{
|
||||||
|
new HitCircle
|
||||||
|
{
|
||||||
|
Position = new Vector2(0),
|
||||||
|
StartTime = 0
|
||||||
|
},
|
||||||
|
new HitCircle
|
||||||
|
{
|
||||||
|
Position = OsuPlayfield.BASE_SIZE,
|
||||||
|
StartTime = 1000
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
AddStep("save beatmap", () => Editor.Save());
|
AddStep("save beatmap", () => Editor.Save());
|
||||||
AddAssert("new beatmap persisted", () =>
|
AddAssert("new beatmap persisted", () =>
|
||||||
{
|
{
|
||||||
@ -111,13 +134,27 @@ namespace osu.Game.Tests.Visual.Editing
|
|||||||
});
|
});
|
||||||
AddAssert("can save again", () => Editor.Save());
|
AddAssert("can save again", () => Editor.Save());
|
||||||
|
|
||||||
AddStep("create new difficulty", () => Editor.CreateNewDifficulty(new OsuRuleset().RulesetInfo));
|
AddStep("create new difficulty", () => Editor.CreateNewDifficulty(sameRuleset ? new OsuRuleset().RulesetInfo : new CatchRuleset().RulesetInfo));
|
||||||
|
|
||||||
|
if (sameRuleset)
|
||||||
|
{
|
||||||
|
AddUntilStep("wait for dialog", () => DialogOverlay.CurrentDialog is CreateNewDifficultyDialog);
|
||||||
|
AddStep("confirm creation with no objects", () => DialogOverlay.CurrentDialog.PerformOkAction());
|
||||||
|
}
|
||||||
|
|
||||||
AddUntilStep("wait for created", () =>
|
AddUntilStep("wait for created", () =>
|
||||||
{
|
{
|
||||||
string difficultyName = Editor.ChildrenOfType<EditorBeatmap>().SingleOrDefault()?.BeatmapInfo.DifficultyName;
|
string difficultyName = Editor.ChildrenOfType<EditorBeatmap>().SingleOrDefault()?.BeatmapInfo.DifficultyName;
|
||||||
return difficultyName != null && difficultyName != firstDifficultyName;
|
return difficultyName != null && difficultyName != firstDifficultyName;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
AddAssert("created difficulty has timing point", () =>
|
||||||
|
{
|
||||||
|
var timingPoint = EditorBeatmap.ControlPointInfo.TimingPoints.Single();
|
||||||
|
return timingPoint.Time == 0 && timingPoint.BeatLength == 1000;
|
||||||
|
});
|
||||||
|
AddAssert("created difficulty has no objects", () => EditorBeatmap.HitObjects.Count == 0);
|
||||||
|
|
||||||
AddStep("set unique difficulty name", () => EditorBeatmap.BeatmapInfo.DifficultyName = secondDifficultyName);
|
AddStep("set unique difficulty name", () => EditorBeatmap.BeatmapInfo.DifficultyName = secondDifficultyName);
|
||||||
AddStep("save beatmap", () => Editor.Save());
|
AddStep("save beatmap", () => Editor.Save());
|
||||||
AddAssert("new beatmap persisted", () =>
|
AddAssert("new beatmap persisted", () =>
|
||||||
@ -133,11 +170,111 @@ namespace osu.Game.Tests.Visual.Editing
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestCreateNewBeatmapFailsWithBlankNamedDifficulties()
|
public void TestCopyDifficulty()
|
||||||
|
{
|
||||||
|
string originalDifficultyName = Guid.NewGuid().ToString();
|
||||||
|
string copyDifficultyName = $"{originalDifficultyName} (copy)";
|
||||||
|
|
||||||
|
AddStep("set unique difficulty name", () => EditorBeatmap.BeatmapInfo.DifficultyName = originalDifficultyName);
|
||||||
|
AddStep("add timing point", () => EditorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = 1000 }));
|
||||||
|
AddStep("add hitobjects", () => EditorBeatmap.AddRange(new[]
|
||||||
|
{
|
||||||
|
new HitCircle
|
||||||
|
{
|
||||||
|
Position = new Vector2(0),
|
||||||
|
StartTime = 0
|
||||||
|
},
|
||||||
|
new HitCircle
|
||||||
|
{
|
||||||
|
Position = OsuPlayfield.BASE_SIZE,
|
||||||
|
StartTime = 1000
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
AddStep("set approach rate", () => EditorBeatmap.Difficulty.ApproachRate = 4);
|
||||||
|
AddStep("set combo colours", () =>
|
||||||
|
{
|
||||||
|
var beatmapSkin = EditorBeatmap.BeatmapSkin.AsNonNull();
|
||||||
|
beatmapSkin.ComboColours.Clear();
|
||||||
|
beatmapSkin.ComboColours.AddRange(new[]
|
||||||
|
{
|
||||||
|
new Colour4(255, 0, 0, 255),
|
||||||
|
new Colour4(0, 0, 255, 255)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
AddStep("set status & online ID", () =>
|
||||||
|
{
|
||||||
|
EditorBeatmap.BeatmapInfo.OnlineID = 123456;
|
||||||
|
EditorBeatmap.BeatmapInfo.Status = BeatmapOnlineStatus.WIP;
|
||||||
|
});
|
||||||
|
|
||||||
|
AddStep("save beatmap", () => Editor.Save());
|
||||||
|
AddAssert("new beatmap persisted", () =>
|
||||||
|
{
|
||||||
|
var beatmap = beatmapManager.QueryBeatmap(b => b.DifficultyName == originalDifficultyName);
|
||||||
|
var set = beatmapManager.QueryBeatmapSet(s => s.ID == EditorBeatmap.BeatmapInfo.BeatmapSet.ID);
|
||||||
|
|
||||||
|
return beatmap != null
|
||||||
|
&& beatmap.DifficultyName == originalDifficultyName
|
||||||
|
&& set != null
|
||||||
|
&& set.PerformRead(s => s.Beatmaps.Single().ID == beatmap.ID);
|
||||||
|
});
|
||||||
|
AddAssert("can save again", () => Editor.Save());
|
||||||
|
|
||||||
|
AddStep("create new difficulty", () => Editor.CreateNewDifficulty(new OsuRuleset().RulesetInfo));
|
||||||
|
|
||||||
|
AddUntilStep("wait for dialog", () => DialogOverlay.CurrentDialog is CreateNewDifficultyDialog);
|
||||||
|
AddStep("confirm creation as a copy", () => DialogOverlay.CurrentDialog.Buttons.ElementAt(1).TriggerClick());
|
||||||
|
|
||||||
|
AddUntilStep("wait for created", () =>
|
||||||
|
{
|
||||||
|
string difficultyName = Editor.ChildrenOfType<EditorBeatmap>().SingleOrDefault()?.BeatmapInfo.DifficultyName;
|
||||||
|
return difficultyName != null && difficultyName != originalDifficultyName;
|
||||||
|
});
|
||||||
|
|
||||||
|
AddAssert("created difficulty has copy suffix in name", () => EditorBeatmap.BeatmapInfo.DifficultyName == copyDifficultyName);
|
||||||
|
AddAssert("created difficulty has timing point", () =>
|
||||||
|
{
|
||||||
|
var timingPoint = EditorBeatmap.ControlPointInfo.TimingPoints.Single();
|
||||||
|
return timingPoint.Time == 0 && timingPoint.BeatLength == 1000;
|
||||||
|
});
|
||||||
|
AddAssert("created difficulty has objects", () => EditorBeatmap.HitObjects.Count == 2);
|
||||||
|
AddAssert("approach rate correctly copied", () => EditorBeatmap.Difficulty.ApproachRate == 4);
|
||||||
|
AddAssert("combo colours correctly copied", () => EditorBeatmap.BeatmapSkin.AsNonNull().ComboColours.Count == 2);
|
||||||
|
|
||||||
|
AddAssert("status not copied", () => EditorBeatmap.BeatmapInfo.Status == BeatmapOnlineStatus.None);
|
||||||
|
AddAssert("online ID not copied", () => EditorBeatmap.BeatmapInfo.OnlineID == -1);
|
||||||
|
|
||||||
|
AddStep("save beatmap", () => Editor.Save());
|
||||||
|
|
||||||
|
BeatmapInfo refetchedBeatmap = null;
|
||||||
|
Live<BeatmapSetInfo> refetchedBeatmapSet = null;
|
||||||
|
|
||||||
|
AddStep("refetch from database", () =>
|
||||||
|
{
|
||||||
|
refetchedBeatmap = beatmapManager.QueryBeatmap(b => b.DifficultyName == copyDifficultyName);
|
||||||
|
refetchedBeatmapSet = beatmapManager.QueryBeatmapSet(s => s.ID == EditorBeatmap.BeatmapInfo.BeatmapSet.ID);
|
||||||
|
});
|
||||||
|
|
||||||
|
AddAssert("new beatmap persisted", () =>
|
||||||
|
{
|
||||||
|
return refetchedBeatmap != null
|
||||||
|
&& refetchedBeatmap.DifficultyName == copyDifficultyName
|
||||||
|
&& refetchedBeatmapSet != null
|
||||||
|
&& refetchedBeatmapSet.PerformRead(s =>
|
||||||
|
s.Beatmaps.Count == 2
|
||||||
|
&& s.Beatmaps.Any(b => b.DifficultyName == originalDifficultyName)
|
||||||
|
&& s.Beatmaps.Any(b => b.DifficultyName == copyDifficultyName));
|
||||||
|
});
|
||||||
|
AddAssert("old beatmap file not deleted", () => refetchedBeatmapSet.AsNonNull().PerformRead(s => s.Files.Count == 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestCreateMultipleNewDifficultiesSucceeds()
|
||||||
{
|
{
|
||||||
Guid setId = Guid.Empty;
|
Guid setId = Guid.Empty;
|
||||||
|
|
||||||
AddStep("retrieve set ID", () => setId = EditorBeatmap.BeatmapInfo.BeatmapSet!.ID);
|
AddStep("retrieve set ID", () => setId = EditorBeatmap.BeatmapInfo.BeatmapSet!.ID);
|
||||||
|
AddStep("set difficulty name", () => EditorBeatmap.BeatmapInfo.DifficultyName = "New Difficulty");
|
||||||
AddStep("save beatmap", () => Editor.Save());
|
AddStep("save beatmap", () => Editor.Save());
|
||||||
AddAssert("new beatmap persisted", () =>
|
AddAssert("new beatmap persisted", () =>
|
||||||
{
|
{
|
||||||
@ -146,15 +283,24 @@ namespace osu.Game.Tests.Visual.Editing
|
|||||||
});
|
});
|
||||||
|
|
||||||
AddStep("try to create new difficulty", () => Editor.CreateNewDifficulty(new OsuRuleset().RulesetInfo));
|
AddStep("try to create new difficulty", () => Editor.CreateNewDifficulty(new OsuRuleset().RulesetInfo));
|
||||||
AddAssert("beatmap set unchanged", () =>
|
AddUntilStep("wait for dialog", () => DialogOverlay.CurrentDialog is CreateNewDifficultyDialog);
|
||||||
|
AddStep("confirm creation with no objects", () => DialogOverlay.CurrentDialog.PerformOkAction());
|
||||||
|
|
||||||
|
AddUntilStep("wait for created", () =>
|
||||||
|
{
|
||||||
|
string difficultyName = Editor.ChildrenOfType<EditorBeatmap>().SingleOrDefault()?.BeatmapInfo.DifficultyName;
|
||||||
|
return difficultyName != null && difficultyName != "New Difficulty";
|
||||||
|
});
|
||||||
|
AddAssert("new difficulty has correct name", () => EditorBeatmap.BeatmapInfo.DifficultyName == "New Difficulty (1)");
|
||||||
|
AddAssert("new difficulty persisted", () =>
|
||||||
{
|
{
|
||||||
var set = beatmapManager.QueryBeatmapSet(s => s.ID == setId);
|
var set = beatmapManager.QueryBeatmapSet(s => s.ID == setId);
|
||||||
return set != null && set.PerformRead(s => s.Beatmaps.Count == 1 && s.Files.Count == 1);
|
return set != null && set.PerformRead(s => s.Beatmaps.Count == 2 && s.Files.Count == 2);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestCreateNewBeatmapFailsWithSameNamedDifficulties()
|
public void TestSavingBeatmapFailsWithSameNamedDifficulties([Values] bool sameRuleset)
|
||||||
{
|
{
|
||||||
Guid setId = Guid.Empty;
|
Guid setId = Guid.Empty;
|
||||||
const string duplicate_difficulty_name = "duplicate";
|
const string duplicate_difficulty_name = "duplicate";
|
||||||
@ -168,7 +314,14 @@ namespace osu.Game.Tests.Visual.Editing
|
|||||||
return set != null && set.PerformRead(s => s.Beatmaps.Count == 1 && s.Files.Count == 1);
|
return set != null && set.PerformRead(s => s.Beatmaps.Count == 1 && s.Files.Count == 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
AddStep("create new difficulty", () => Editor.CreateNewDifficulty(new OsuRuleset().RulesetInfo));
|
AddStep("create new difficulty", () => Editor.CreateNewDifficulty(sameRuleset ? new OsuRuleset().RulesetInfo : new CatchRuleset().RulesetInfo));
|
||||||
|
|
||||||
|
if (sameRuleset)
|
||||||
|
{
|
||||||
|
AddUntilStep("wait for dialog", () => DialogOverlay.CurrentDialog is CreateNewDifficultyDialog);
|
||||||
|
AddStep("confirm creation with no objects", () => DialogOverlay.CurrentDialog.PerformOkAction());
|
||||||
|
}
|
||||||
|
|
||||||
AddUntilStep("wait for created", () =>
|
AddUntilStep("wait for created", () =>
|
||||||
{
|
{
|
||||||
string difficultyName = Editor.ChildrenOfType<EditorBeatmap>().SingleOrDefault()?.BeatmapInfo.DifficultyName;
|
string difficultyName = Editor.ChildrenOfType<EditorBeatmap>().SingleOrDefault()?.BeatmapInfo.DifficultyName;
|
||||||
|
@ -39,7 +39,8 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
[Resolved]
|
[Resolved]
|
||||||
private OsuGameBase game { get; set; }
|
private OsuGameBase game { get; set; }
|
||||||
|
|
||||||
private TestSpectatorClient spectatorClient;
|
private TestSpectatorClient spectatorClient => dependenciesScreen.SpectatorClient;
|
||||||
|
private DependenciesScreen dependenciesScreen;
|
||||||
private SoloSpectator spectatorScreen;
|
private SoloSpectator spectatorScreen;
|
||||||
|
|
||||||
private BeatmapSetInfo importedBeatmap;
|
private BeatmapSetInfo importedBeatmap;
|
||||||
@ -48,16 +49,16 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
[SetUpSteps]
|
[SetUpSteps]
|
||||||
public void SetupSteps()
|
public void SetupSteps()
|
||||||
{
|
{
|
||||||
DependenciesScreen dependenciesScreen = null;
|
|
||||||
|
|
||||||
AddStep("load dependencies", () =>
|
AddStep("load dependencies", () =>
|
||||||
{
|
{
|
||||||
spectatorClient = new TestSpectatorClient();
|
LoadScreen(dependenciesScreen = new DependenciesScreen());
|
||||||
|
|
||||||
// The screen gets suspended so it stops receiving updates.
|
// The dependencies screen gets suspended so it stops receiving updates. So its children are manually added to the test scene instead.
|
||||||
Child = spectatorClient;
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
LoadScreen(dependenciesScreen = new DependenciesScreen(spectatorClient));
|
dependenciesScreen.UserLookupCache,
|
||||||
|
dependenciesScreen.SpectatorClient,
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
AddUntilStep("wait for dependencies to load", () => dependenciesScreen.IsLoaded);
|
AddUntilStep("wait for dependencies to load", () => dependenciesScreen.IsLoaded);
|
||||||
@ -335,12 +336,10 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
private class DependenciesScreen : OsuScreen
|
private class DependenciesScreen : OsuScreen
|
||||||
{
|
{
|
||||||
[Cached(typeof(SpectatorClient))]
|
[Cached(typeof(SpectatorClient))]
|
||||||
public readonly TestSpectatorClient Client;
|
public readonly TestSpectatorClient SpectatorClient = new TestSpectatorClient();
|
||||||
|
|
||||||
public DependenciesScreen(TestSpectatorClient client)
|
[Cached(typeof(UserLookupCache))]
|
||||||
{
|
public readonly TestUserLookupCache UserLookupCache = new TestUserLookupCache();
|
||||||
Client = client;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,10 @@ namespace osu.Game.Tests.Visual.Menus
|
|||||||
base.SetUpSteps();
|
base.SetUpSteps();
|
||||||
|
|
||||||
AddAssert("no screen offset applied", () => Game.ScreenOffsetContainer.X == 0f);
|
AddAssert("no screen offset applied", () => Game.ScreenOffsetContainer.X == 0f);
|
||||||
|
|
||||||
|
// avoids mouse interacting with settings overlay.
|
||||||
|
AddStep("move mouse to centre", () => InputManager.MoveMouseTo(Game.ScreenSpaceDrawQuad.Centre));
|
||||||
|
|
||||||
AddUntilStep("wait for overlays", () => Game.Settings.IsLoaded && Game.Notifications.IsLoaded);
|
AddUntilStep("wait for overlays", () => Game.Settings.IsLoaded && Game.Notifications.IsLoaded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,6 @@ using osu.Framework.Platform;
|
|||||||
using osu.Framework.Screens;
|
using osu.Framework.Screens;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Database;
|
|
||||||
using osu.Game.Online.Multiplayer;
|
using osu.Game.Online.Multiplayer;
|
||||||
using osu.Game.Online.Rooms;
|
using osu.Game.Online.Rooms;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
@ -39,10 +38,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
|
|
||||||
private TestMultiplayerComponents multiplayerComponents;
|
private TestMultiplayerComponents multiplayerComponents;
|
||||||
|
|
||||||
protected TestMultiplayerClient Client => multiplayerComponents.Client;
|
protected TestMultiplayerClient MultiplayerClient => multiplayerComponents.MultiplayerClient;
|
||||||
|
|
||||||
[Cached(typeof(UserLookupCache))]
|
|
||||||
private UserLookupCache lookupCache = new TestUserLookupCache();
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(GameHost host, AudioManager audio)
|
private void load(GameHost host, AudioManager audio)
|
||||||
@ -75,10 +71,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
QueueMode = { Value = Mode },
|
QueueMode = { Value = Mode },
|
||||||
Playlist =
|
Playlist =
|
||||||
{
|
{
|
||||||
new PlaylistItem
|
new PlaylistItem(InitialBeatmap)
|
||||||
{
|
{
|
||||||
Beatmap = { Value = InitialBeatmap },
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
|
||||||
Ruleset = { Value = new OsuRuleset().RulesetInfo },
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
@ -88,21 +83,21 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
|
|
||||||
ClickButtonWhenEnabled<MultiplayerMatchSettingsOverlay.CreateOrUpdateButton>();
|
ClickButtonWhenEnabled<MultiplayerMatchSettingsOverlay.CreateOrUpdateButton>();
|
||||||
|
|
||||||
AddUntilStep("wait for join", () => Client.RoomJoined);
|
AddUntilStep("wait for join", () => MultiplayerClient.RoomJoined);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestCreatedWithCorrectMode()
|
public void TestCreatedWithCorrectMode()
|
||||||
{
|
{
|
||||||
AddAssert("room created with correct mode", () => Client.APIRoom?.QueueMode.Value == Mode);
|
AddAssert("room created with correct mode", () => MultiplayerClient.APIRoom?.QueueMode.Value == Mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void RunGameplay()
|
protected void RunGameplay()
|
||||||
{
|
{
|
||||||
AddUntilStep("wait for idle", () => Client.LocalUser?.State == MultiplayerUserState.Idle);
|
AddUntilStep("wait for idle", () => MultiplayerClient.LocalUser?.State == MultiplayerUserState.Idle);
|
||||||
ClickButtonWhenEnabled<MultiplayerReadyButton>();
|
ClickButtonWhenEnabled<MultiplayerReadyButton>();
|
||||||
|
|
||||||
AddUntilStep("wait for ready", () => Client.LocalUser?.State == MultiplayerUserState.Ready);
|
AddUntilStep("wait for ready", () => MultiplayerClient.LocalUser?.State == MultiplayerUserState.Ready);
|
||||||
ClickButtonWhenEnabled<MultiplayerReadyButton>();
|
ClickButtonWhenEnabled<MultiplayerReadyButton>();
|
||||||
|
|
||||||
AddUntilStep("wait for player", () => multiplayerComponents.CurrentScreen is Player player && player.IsLoaded);
|
AddUntilStep("wait for player", () => multiplayerComponents.CurrentScreen is Player player && player.IsLoaded);
|
||||||
|
@ -31,19 +31,19 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestFirstItemSelectedByDefault()
|
public void TestFirstItemSelectedByDefault()
|
||||||
{
|
{
|
||||||
AddAssert("first item selected", () => Client.Room?.Settings.PlaylistItemId == Client.APIRoom?.Playlist[0].ID);
|
AddAssert("first item selected", () => MultiplayerClient.Room?.Settings.PlaylistItemId == MultiplayerClient.APIRoom?.Playlist[0].ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestItemAddedToTheEndOfQueue()
|
public void TestItemAddedToTheEndOfQueue()
|
||||||
{
|
{
|
||||||
addItem(() => OtherBeatmap);
|
addItem(() => OtherBeatmap);
|
||||||
AddAssert("playlist has 2 items", () => Client.APIRoom?.Playlist.Count == 2);
|
AddAssert("playlist has 2 items", () => MultiplayerClient.APIRoom?.Playlist.Count == 2);
|
||||||
|
|
||||||
addItem(() => InitialBeatmap);
|
addItem(() => InitialBeatmap);
|
||||||
AddAssert("playlist has 3 items", () => Client.APIRoom?.Playlist.Count == 3);
|
AddAssert("playlist has 3 items", () => MultiplayerClient.APIRoom?.Playlist.Count == 3);
|
||||||
|
|
||||||
AddAssert("first item still selected", () => Client.Room?.Settings.PlaylistItemId == Client.APIRoom?.Playlist[0].ID);
|
AddAssert("first item still selected", () => MultiplayerClient.Room?.Settings.PlaylistItemId == MultiplayerClient.APIRoom?.Playlist[0].ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -51,9 +51,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
{
|
{
|
||||||
RunGameplay();
|
RunGameplay();
|
||||||
|
|
||||||
AddAssert("playlist has only one item", () => Client.APIRoom?.Playlist.Count == 1);
|
AddAssert("playlist has only one item", () => MultiplayerClient.APIRoom?.Playlist.Count == 1);
|
||||||
AddAssert("playlist item is expired", () => Client.APIRoom?.Playlist[0].Expired == true);
|
AddAssert("playlist item is expired", () => MultiplayerClient.APIRoom?.Playlist[0].Expired == true);
|
||||||
AddAssert("last item selected", () => Client.Room?.Settings.PlaylistItemId == Client.APIRoom?.Playlist[0].ID);
|
AddAssert("last item selected", () => MultiplayerClient.Room?.Settings.PlaylistItemId == MultiplayerClient.APIRoom?.Playlist[0].ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -64,13 +64,13 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
|
|
||||||
RunGameplay();
|
RunGameplay();
|
||||||
|
|
||||||
AddAssert("first item expired", () => Client.APIRoom?.Playlist[0].Expired == true);
|
AddAssert("first item expired", () => MultiplayerClient.APIRoom?.Playlist[0].Expired == true);
|
||||||
AddAssert("next item selected", () => Client.Room?.Settings.PlaylistItemId == Client.APIRoom?.Playlist[1].ID);
|
AddAssert("next item selected", () => MultiplayerClient.Room?.Settings.PlaylistItemId == MultiplayerClient.APIRoom?.Playlist[1].ID);
|
||||||
|
|
||||||
RunGameplay();
|
RunGameplay();
|
||||||
|
|
||||||
AddAssert("second item expired", () => Client.APIRoom?.Playlist[1].Expired == true);
|
AddAssert("second item expired", () => MultiplayerClient.APIRoom?.Playlist[1].Expired == true);
|
||||||
AddAssert("next item selected", () => Client.Room?.Settings.PlaylistItemId == Client.APIRoom?.Playlist[2].ID);
|
AddAssert("next item selected", () => MultiplayerClient.Room?.Settings.PlaylistItemId == MultiplayerClient.APIRoom?.Playlist[2].ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -82,10 +82,10 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
// Move to the "other" beatmap.
|
// Move to the "other" beatmap.
|
||||||
RunGameplay();
|
RunGameplay();
|
||||||
|
|
||||||
AddStep("change queue mode", () => Client.ChangeSettings(queueMode: QueueMode.HostOnly));
|
AddStep("change queue mode", () => MultiplayerClient.ChangeSettings(queueMode: QueueMode.HostOnly));
|
||||||
AddAssert("playlist has 3 items", () => Client.APIRoom?.Playlist.Count == 3);
|
AddAssert("playlist has 3 items", () => MultiplayerClient.APIRoom?.Playlist.Count == 3);
|
||||||
AddAssert("item 2 is not expired", () => Client.APIRoom?.Playlist[1].Expired == false);
|
AddAssert("item 2 is not expired", () => MultiplayerClient.APIRoom?.Playlist[1].Expired == false);
|
||||||
AddAssert("current item is the other beatmap", () => Client.Room?.Settings.PlaylistItemId == 2);
|
AddAssert("current item is the other beatmap", () => MultiplayerClient.Room?.Settings.PlaylistItemId == 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -101,10 +101,10 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
addItem(() => OtherBeatmap, new CatchRuleset().RulesetInfo);
|
addItem(() => OtherBeatmap, new CatchRuleset().RulesetInfo);
|
||||||
AddUntilStep("selected beatmap is initial beatmap", () => Beatmap.Value.BeatmapInfo.OnlineID == InitialBeatmap.OnlineID);
|
AddUntilStep("selected beatmap is initial beatmap", () => Beatmap.Value.BeatmapInfo.OnlineID == InitialBeatmap.OnlineID);
|
||||||
|
|
||||||
AddUntilStep("wait for idle", () => Client.LocalUser?.State == MultiplayerUserState.Idle);
|
AddUntilStep("wait for idle", () => MultiplayerClient.LocalUser?.State == MultiplayerUserState.Idle);
|
||||||
ClickButtonWhenEnabled<MultiplayerReadyButton>();
|
ClickButtonWhenEnabled<MultiplayerReadyButton>();
|
||||||
|
|
||||||
AddUntilStep("wait for ready", () => Client.LocalUser?.State == MultiplayerUserState.Ready);
|
AddUntilStep("wait for ready", () => MultiplayerClient.LocalUser?.State == MultiplayerUserState.Ready);
|
||||||
ClickButtonWhenEnabled<MultiplayerReadyButton>();
|
ClickButtonWhenEnabled<MultiplayerReadyButton>();
|
||||||
|
|
||||||
AddUntilStep("wait for player", () => CurrentScreen is Player player && player.IsLoaded);
|
AddUntilStep("wait for player", () => CurrentScreen is Player player && player.IsLoaded);
|
||||||
@ -118,10 +118,10 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
addItem(() => OtherBeatmap, mods: new Mod[] { new OsuModDoubleTime() });
|
addItem(() => OtherBeatmap, mods: new Mod[] { new OsuModDoubleTime() });
|
||||||
AddUntilStep("selected beatmap is initial beatmap", () => Beatmap.Value.BeatmapInfo.OnlineID == InitialBeatmap.OnlineID);
|
AddUntilStep("selected beatmap is initial beatmap", () => Beatmap.Value.BeatmapInfo.OnlineID == InitialBeatmap.OnlineID);
|
||||||
|
|
||||||
AddUntilStep("wait for idle", () => Client.LocalUser?.State == MultiplayerUserState.Idle);
|
AddUntilStep("wait for idle", () => MultiplayerClient.LocalUser?.State == MultiplayerUserState.Idle);
|
||||||
ClickButtonWhenEnabled<MultiplayerReadyButton>();
|
ClickButtonWhenEnabled<MultiplayerReadyButton>();
|
||||||
|
|
||||||
AddUntilStep("wait for ready", () => Client.LocalUser?.State == MultiplayerUserState.Ready);
|
AddUntilStep("wait for ready", () => MultiplayerClient.LocalUser?.State == MultiplayerUserState.Ready);
|
||||||
ClickButtonWhenEnabled<MultiplayerReadyButton>();
|
ClickButtonWhenEnabled<MultiplayerReadyButton>();
|
||||||
|
|
||||||
AddUntilStep("wait for player", () => CurrentScreen is Player player && player.IsLoaded);
|
AddUntilStep("wait for player", () => CurrentScreen is Player player && player.IsLoaded);
|
||||||
|
@ -37,10 +37,10 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
AddStep("end joining room", () => joiningRoomOperation.Dispose());
|
AddStep("end joining room", () => joiningRoomOperation.Dispose());
|
||||||
assertButtonEnableState(true);
|
assertButtonEnableState(true);
|
||||||
|
|
||||||
AddStep("disconnect client", () => Client.Disconnect());
|
AddStep("disconnect client", () => MultiplayerClient.Disconnect());
|
||||||
assertButtonEnableState(false);
|
assertButtonEnableState(false);
|
||||||
|
|
||||||
AddStep("re-connect client", () => Client.Connect());
|
AddStep("re-connect client", () => MultiplayerClient.Connect());
|
||||||
assertButtonEnableState(true);
|
assertButtonEnableState(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,19 +53,13 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
Type = { Value = MatchType.HeadToHead },
|
Type = { Value = MatchType.HeadToHead },
|
||||||
Playlist =
|
Playlist =
|
||||||
{
|
{
|
||||||
new PlaylistItem
|
new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo)
|
||||||
{
|
{
|
||||||
Beatmap =
|
BeatmapInfo =
|
||||||
{
|
{
|
||||||
Value = new TestBeatmap(new OsuRuleset().RulesetInfo)
|
StarRating = 2.5
|
||||||
{
|
|
||||||
BeatmapInfo =
|
|
||||||
{
|
|
||||||
StarRating = 2.5
|
|
||||||
}
|
|
||||||
}.BeatmapInfo,
|
|
||||||
}
|
}
|
||||||
}
|
}.BeatmapInfo)
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
createLoungeRoom(new Room
|
createLoungeRoom(new Room
|
||||||
@ -76,26 +70,20 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
Type = { Value = MatchType.HeadToHead },
|
Type = { Value = MatchType.HeadToHead },
|
||||||
Playlist =
|
Playlist =
|
||||||
{
|
{
|
||||||
new PlaylistItem
|
new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo)
|
||||||
{
|
{
|
||||||
Beatmap =
|
BeatmapInfo =
|
||||||
{
|
{
|
||||||
Value = new TestBeatmap(new OsuRuleset().RulesetInfo)
|
StarRating = 2.5,
|
||||||
|
Metadata =
|
||||||
{
|
{
|
||||||
BeatmapInfo =
|
Artist = "very very very very very very very very very long artist",
|
||||||
{
|
ArtistUnicode = "very very very very very very very very very long artist",
|
||||||
StarRating = 2.5,
|
Title = "very very very very very very very very very very very long title",
|
||||||
Metadata =
|
TitleUnicode = "very very very very very very very very very very very long title",
|
||||||
{
|
}
|
||||||
Artist = "very very very very very very very very very long artist",
|
|
||||||
ArtistUnicode = "very very very very very very very very very long artist",
|
|
||||||
Title = "very very very very very very very very very very very long title",
|
|
||||||
TitleUnicode = "very very very very very very very very very very very long title",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.BeatmapInfo,
|
|
||||||
}
|
}
|
||||||
}
|
}.BeatmapInfo)
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
createLoungeRoom(new Room
|
createLoungeRoom(new Room
|
||||||
@ -105,32 +93,20 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
EndDate = { Value = DateTimeOffset.Now.AddDays(1) },
|
EndDate = { Value = DateTimeOffset.Now.AddDays(1) },
|
||||||
Playlist =
|
Playlist =
|
||||||
{
|
{
|
||||||
new PlaylistItem
|
new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo)
|
||||||
{
|
{
|
||||||
Beatmap =
|
BeatmapInfo =
|
||||||
{
|
{
|
||||||
Value = new TestBeatmap(new OsuRuleset().RulesetInfo)
|
StarRating = 2.5
|
||||||
{
|
|
||||||
BeatmapInfo =
|
|
||||||
{
|
|
||||||
StarRating = 2.5
|
|
||||||
}
|
|
||||||
}.BeatmapInfo,
|
|
||||||
}
|
}
|
||||||
},
|
}.BeatmapInfo),
|
||||||
new PlaylistItem
|
new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo)
|
||||||
{
|
{
|
||||||
Beatmap =
|
BeatmapInfo =
|
||||||
{
|
{
|
||||||
Value = new TestBeatmap(new OsuRuleset().RulesetInfo)
|
StarRating = 4.5
|
||||||
{
|
|
||||||
BeatmapInfo =
|
|
||||||
{
|
|
||||||
StarRating = 4.5
|
|
||||||
}
|
|
||||||
}.BeatmapInfo,
|
|
||||||
}
|
}
|
||||||
}
|
}.BeatmapInfo)
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
createLoungeRoom(new Room
|
createLoungeRoom(new Room
|
||||||
|
@ -17,6 +17,7 @@ using osu.Game.Beatmaps.Drawables;
|
|||||||
using osu.Game.Database;
|
using osu.Game.Database;
|
||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
using osu.Game.Models;
|
using osu.Game.Models;
|
||||||
|
using osu.Game.Online.API;
|
||||||
using osu.Game.Online.Rooms;
|
using osu.Game.Online.Rooms;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Rulesets.Osu;
|
using osu.Game.Rulesets.Osu;
|
||||||
@ -29,16 +30,13 @@ using osuTK.Input;
|
|||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Multiplayer
|
namespace osu.Game.Tests.Visual.Multiplayer
|
||||||
{
|
{
|
||||||
public class TestSceneDrawableRoomPlaylist : OsuManualInputManagerTestScene
|
public class TestSceneDrawableRoomPlaylist : MultiplayerTestScene
|
||||||
{
|
{
|
||||||
private TestPlaylist playlist;
|
private TestPlaylist playlist;
|
||||||
|
|
||||||
private BeatmapManager manager;
|
private BeatmapManager manager;
|
||||||
private RulesetStore rulesets;
|
private RulesetStore rulesets;
|
||||||
|
|
||||||
[Cached(typeof(UserLookupCache))]
|
|
||||||
private readonly TestUserLookupCache userLookupCache = new TestUserLookupCache();
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(GameHost host, AudioManager audio)
|
private void load(GameHost host, AudioManager audio)
|
||||||
{
|
{
|
||||||
@ -170,7 +168,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
assertDownloadButtonVisible(false);
|
assertDownloadButtonVisible(false);
|
||||||
|
|
||||||
void assertDownloadButtonVisible(bool visible) => AddUntilStep($"download button {(visible ? "shown" : "hidden")}",
|
void assertDownloadButtonVisible(bool visible) => AddUntilStep($"download button {(visible ? "shown" : "hidden")}",
|
||||||
() => playlist.ChildrenOfType<BeatmapDownloadButton>().Single().Alpha == (visible ? 1 : 0));
|
() => playlist.ChildrenOfType<BeatmapDownloadButton>().SingleOrDefault()?.Alpha == (visible ? 1 : 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -211,29 +209,27 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
Size = new Vector2(500, 300),
|
Size = new Vector2(500, 300),
|
||||||
Items =
|
Items =
|
||||||
{
|
{
|
||||||
new PlaylistItem
|
new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo)
|
||||||
{
|
{
|
||||||
ID = 0,
|
ID = 0,
|
||||||
Beatmap = { Value = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo },
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID,
|
||||||
Ruleset = { Value = new OsuRuleset().RulesetInfo },
|
|
||||||
Expired = true,
|
Expired = true,
|
||||||
RequiredMods =
|
RequiredMods = new[]
|
||||||
{
|
{
|
||||||
new OsuModHardRock(),
|
new APIMod(new OsuModHardRock()),
|
||||||
new OsuModDoubleTime(),
|
new APIMod(new OsuModDoubleTime()),
|
||||||
new OsuModAutoplay()
|
new APIMod(new OsuModAutoplay())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new PlaylistItem
|
new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo)
|
||||||
{
|
{
|
||||||
ID = 1,
|
ID = 1,
|
||||||
Beatmap = { Value = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo },
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID,
|
||||||
Ruleset = { Value = new OsuRuleset().RulesetInfo },
|
RequiredMods = new[]
|
||||||
RequiredMods =
|
|
||||||
{
|
{
|
||||||
new OsuModHardRock(),
|
new APIMod(new OsuModHardRock()),
|
||||||
new OsuModDoubleTime(),
|
new APIMod(new OsuModDoubleTime()),
|
||||||
new OsuModAutoplay()
|
new APIMod(new OsuModAutoplay())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -264,7 +260,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void moveToItem(int index, Vector2? offset = null)
|
private void moveToItem(int index, Vector2? offset = null)
|
||||||
=> AddStep($"move mouse to item {index}", () => InputManager.MoveMouseTo(playlist.ChildrenOfType<DifficultyIcon>().ElementAt(index), offset));
|
=> AddStep($"move mouse to item {index}", () => InputManager.MoveMouseTo(playlist.ChildrenOfType<DrawableRoomPlaylistItem>().ElementAt(index), offset));
|
||||||
|
|
||||||
private void moveToDragger(int index, Vector2? offset = null) => AddStep($"move mouse to dragger {index}", () =>
|
private void moveToDragger(int index, Vector2? offset = null) => AddStep($"move mouse to dragger {index}", () =>
|
||||||
{
|
{
|
||||||
@ -295,31 +291,27 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
|
|
||||||
for (int i = 0; i < 20; i++)
|
for (int i = 0; i < 20; i++)
|
||||||
{
|
{
|
||||||
playlist.Items.Add(new PlaylistItem
|
playlist.Items.Add(new PlaylistItem(i % 2 == 1
|
||||||
|
? new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo
|
||||||
|
: new BeatmapInfo
|
||||||
|
{
|
||||||
|
Metadata = new BeatmapMetadata
|
||||||
|
{
|
||||||
|
Artist = "Artist",
|
||||||
|
Author = new RealmUser { Username = "Creator name here" },
|
||||||
|
Title = "Long title used to check background colour",
|
||||||
|
},
|
||||||
|
BeatmapSet = new BeatmapSetInfo()
|
||||||
|
})
|
||||||
{
|
{
|
||||||
ID = i,
|
ID = i,
|
||||||
OwnerID = 2,
|
OwnerID = 2,
|
||||||
Beatmap =
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID,
|
||||||
|
RequiredMods = new[]
|
||||||
{
|
{
|
||||||
Value = i % 2 == 1
|
new APIMod(new OsuModHardRock()),
|
||||||
? new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo
|
new APIMod(new OsuModDoubleTime()),
|
||||||
: new BeatmapInfo
|
new APIMod(new OsuModAutoplay())
|
||||||
{
|
|
||||||
Metadata = new BeatmapMetadata
|
|
||||||
{
|
|
||||||
Artist = "Artist",
|
|
||||||
Author = new RealmUser { Username = "Creator name here" },
|
|
||||||
Title = "Long title used to check background colour",
|
|
||||||
},
|
|
||||||
BeatmapSet = new BeatmapSetInfo()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Ruleset = { Value = new OsuRuleset().RulesetInfo },
|
|
||||||
RequiredMods =
|
|
||||||
{
|
|
||||||
new OsuModHardRock(),
|
|
||||||
new OsuModDoubleTime(),
|
|
||||||
new OsuModAutoplay()
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -343,17 +335,16 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
|
|
||||||
foreach (var b in beatmaps())
|
foreach (var b in beatmaps())
|
||||||
{
|
{
|
||||||
playlist.Items.Add(new PlaylistItem
|
playlist.Items.Add(new PlaylistItem(b)
|
||||||
{
|
{
|
||||||
ID = index++,
|
ID = index++,
|
||||||
OwnerID = 2,
|
OwnerID = 2,
|
||||||
Beatmap = { Value = b },
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID,
|
||||||
Ruleset = { Value = new OsuRuleset().RulesetInfo },
|
RequiredMods = new[]
|
||||||
RequiredMods =
|
|
||||||
{
|
{
|
||||||
new OsuModHardRock(),
|
new APIMod(new OsuModHardRock()),
|
||||||
new OsuModDoubleTime(),
|
new APIMod(new OsuModDoubleTime()),
|
||||||
new OsuModAutoplay()
|
new APIMod(new OsuModAutoplay())
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Extensions;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Online.Multiplayer;
|
using osu.Game.Online.Multiplayer;
|
||||||
@ -21,7 +22,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestFirstItemSelectedByDefault()
|
public void TestFirstItemSelectedByDefault()
|
||||||
{
|
{
|
||||||
AddAssert("first item selected", () => Client.Room?.Settings.PlaylistItemId == Client.APIRoom?.Playlist[0].ID);
|
AddAssert("first item selected", () => MultiplayerClient.Room?.Settings.PlaylistItemId == MultiplayerClient.APIRoom?.Playlist[0].ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -29,7 +30,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
{
|
{
|
||||||
selectNewItem(() => InitialBeatmap);
|
selectNewItem(() => InitialBeatmap);
|
||||||
|
|
||||||
AddAssert("playlist item still selected", () => Client.Room?.Settings.PlaylistItemId == Client.APIRoom?.Playlist[0].ID);
|
AddAssert("playlist item still selected", () => MultiplayerClient.Room?.Settings.PlaylistItemId == MultiplayerClient.APIRoom?.Playlist[0].ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -37,7 +38,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
{
|
{
|
||||||
selectNewItem(() => OtherBeatmap);
|
selectNewItem(() => OtherBeatmap);
|
||||||
|
|
||||||
AddAssert("playlist item still selected", () => Client.Room?.Settings.PlaylistItemId == Client.APIRoom?.Playlist[0].ID);
|
AddAssert("playlist item still selected", () => MultiplayerClient.Room?.Settings.PlaylistItemId == MultiplayerClient.APIRoom?.Playlist[0].ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -45,10 +46,10 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
{
|
{
|
||||||
RunGameplay();
|
RunGameplay();
|
||||||
|
|
||||||
AddAssert("playlist contains two items", () => Client.APIRoom?.Playlist.Count == 2);
|
AddAssert("playlist contains two items", () => MultiplayerClient.APIRoom?.Playlist.Count == 2);
|
||||||
AddAssert("first playlist item expired", () => Client.APIRoom?.Playlist[0].Expired == true);
|
AddAssert("first playlist item expired", () => MultiplayerClient.APIRoom?.Playlist[0].Expired == true);
|
||||||
AddAssert("second playlist item not expired", () => Client.APIRoom?.Playlist[1].Expired == false);
|
AddAssert("second playlist item not expired", () => MultiplayerClient.APIRoom?.Playlist[1].Expired == false);
|
||||||
AddAssert("second playlist item selected", () => Client.Room?.Settings.PlaylistItemId == Client.APIRoom?.Playlist[1].ID);
|
AddAssert("second playlist item selected", () => MultiplayerClient.Room?.Settings.PlaylistItemId == MultiplayerClient.APIRoom?.Playlist[1].ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -57,23 +58,23 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
RunGameplay();
|
RunGameplay();
|
||||||
|
|
||||||
IBeatmapInfo firstBeatmap = null;
|
IBeatmapInfo firstBeatmap = null;
|
||||||
AddStep("get first playlist item beatmap", () => firstBeatmap = Client.APIRoom?.Playlist[0].Beatmap.Value);
|
AddStep("get first playlist item beatmap", () => firstBeatmap = MultiplayerClient.APIRoom?.Playlist[0].Beatmap);
|
||||||
|
|
||||||
selectNewItem(() => OtherBeatmap);
|
selectNewItem(() => OtherBeatmap);
|
||||||
|
|
||||||
AddAssert("first playlist item hasn't changed", () => Client.APIRoom?.Playlist[0].Beatmap.Value == firstBeatmap);
|
AddAssert("first playlist item hasn't changed", () => MultiplayerClient.APIRoom?.Playlist[0].Beatmap == firstBeatmap);
|
||||||
AddAssert("second playlist item changed", () => Client.APIRoom?.Playlist[1].Beatmap.Value != firstBeatmap);
|
AddAssert("second playlist item changed", () => MultiplayerClient.APIRoom?.Playlist[1].Beatmap != firstBeatmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestSettingsUpdatedWhenChangingQueueMode()
|
public void TestSettingsUpdatedWhenChangingQueueMode()
|
||||||
{
|
{
|
||||||
AddStep("change queue mode", () => Client.ChangeSettings(new MultiplayerRoomSettings
|
AddStep("change queue mode", () => MultiplayerClient.ChangeSettings(new MultiplayerRoomSettings
|
||||||
{
|
{
|
||||||
QueueMode = QueueMode.AllPlayers
|
QueueMode = QueueMode.AllPlayers
|
||||||
}));
|
}).WaitSafely());
|
||||||
|
|
||||||
AddUntilStep("api room updated", () => Client.APIRoom?.QueueMode.Value == QueueMode.AllPlayers);
|
AddUntilStep("api room updated", () => MultiplayerClient.APIRoom?.QueueMode.Value == QueueMode.AllPlayers);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -81,7 +82,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
{
|
{
|
||||||
addItem(() => OtherBeatmap);
|
addItem(() => OtherBeatmap);
|
||||||
|
|
||||||
AddAssert("playlist contains two items", () => Client.APIRoom?.Playlist.Count == 2);
|
AddAssert("playlist contains two items", () => MultiplayerClient.APIRoom?.Playlist.Count == 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void selectNewItem(Func<BeatmapInfo> beatmap)
|
private void selectNewItem(Func<BeatmapInfo> beatmap)
|
||||||
@ -104,7 +105,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
AddStep("select other beatmap", () => ((Screens.Select.SongSelect)CurrentSubScreen).FinaliseSelection(otherBeatmap = beatmap()));
|
AddStep("select other beatmap", () => ((Screens.Select.SongSelect)CurrentSubScreen).FinaliseSelection(otherBeatmap = beatmap()));
|
||||||
|
|
||||||
AddUntilStep("wait for return to match", () => CurrentSubScreen is MultiplayerMatchSubScreen);
|
AddUntilStep("wait for return to match", () => CurrentSubScreen is MultiplayerMatchSubScreen);
|
||||||
AddUntilStep("selected item is new beatmap", () => (CurrentSubScreen as MultiplayerMatchSubScreen)?.SelectedItem.Value?.BeatmapID == otherBeatmap.OnlineID);
|
AddUntilStep("selected item is new beatmap", () => (CurrentSubScreen as MultiplayerMatchSubScreen)?.SelectedItem.Value?.Beatmap.OnlineID == otherBeatmap.OnlineID);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addItem(Func<BeatmapInfo> beatmap)
|
private void addItem(Func<BeatmapInfo> beatmap)
|
||||||
|
@ -44,15 +44,20 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestBasicListChanges()
|
public void TestBasicListChanges()
|
||||||
{
|
{
|
||||||
AddStep("add rooms", () => RoomManager.AddRooms(3));
|
AddStep("add rooms", () => RoomManager.AddRooms(5, withSpotlightRooms: true));
|
||||||
|
|
||||||
AddAssert("has 3 rooms", () => container.Rooms.Count == 3);
|
AddAssert("has 5 rooms", () => container.Rooms.Count == 5);
|
||||||
AddStep("remove first room", () => RoomManager.RemoveRoom(RoomManager.Rooms.FirstOrDefault()));
|
|
||||||
AddAssert("has 2 rooms", () => container.Rooms.Count == 2);
|
AddAssert("all spotlights at top", () => container.Rooms
|
||||||
|
.SkipWhile(r => r.Room.Category.Value == RoomCategory.Spotlight)
|
||||||
|
.All(r => r.Room.Category.Value == RoomCategory.Normal));
|
||||||
|
|
||||||
|
AddStep("remove first room", () => RoomManager.RemoveRoom(RoomManager.Rooms.FirstOrDefault(r => r.RoomID.Value == 0)));
|
||||||
|
AddAssert("has 4 rooms", () => container.Rooms.Count == 4);
|
||||||
AddAssert("first room removed", () => container.Rooms.All(r => r.Room.RoomID.Value != 0));
|
AddAssert("first room removed", () => container.Rooms.All(r => r.Room.RoomID.Value != 0));
|
||||||
|
|
||||||
AddStep("select first room", () => container.Rooms.First().TriggerClick());
|
AddStep("select first room", () => container.Rooms.First().TriggerClick());
|
||||||
AddAssert("first room selected", () => checkRoomSelected(RoomManager.Rooms.First()));
|
AddAssert("first spotlight selected", () => checkRoomSelected(RoomManager.Rooms.First(r => r.Category.Value == RoomCategory.Spotlight)));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Game.Online.API;
|
||||||
using osu.Game.Online.Rooms;
|
using osu.Game.Online.Rooms;
|
||||||
using osu.Game.Rulesets.Osu;
|
using osu.Game.Rulesets.Osu;
|
||||||
using osu.Game.Rulesets.Osu.Mods;
|
using osu.Game.Rulesets.Osu.Mods;
|
||||||
@ -31,16 +32,15 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
|
|
||||||
private void createNewItem()
|
private void createNewItem()
|
||||||
{
|
{
|
||||||
SelectedRoom.Value.Playlist.Add(new PlaylistItem
|
SelectedRoom.Value.Playlist.Add(new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo)
|
||||||
{
|
{
|
||||||
ID = SelectedRoom.Value.Playlist.Count,
|
ID = SelectedRoom.Value.Playlist.Count,
|
||||||
Beatmap = { Value = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo },
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID,
|
||||||
Ruleset = { Value = new OsuRuleset().RulesetInfo },
|
RequiredMods = new[]
|
||||||
RequiredMods =
|
|
||||||
{
|
{
|
||||||
new OsuModHardRock(),
|
new APIMod(new OsuModHardRock()),
|
||||||
new OsuModDoubleTime(),
|
new APIMod(new OsuModDoubleTime()),
|
||||||
new OsuModAutoplay()
|
new APIMod(new OsuModAutoplay())
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
foreach ((int userId, var _) in clocks)
|
foreach ((int userId, var _) in clocks)
|
||||||
{
|
{
|
||||||
SpectatorClient.StartPlay(userId, 0);
|
SpectatorClient.StartPlay(userId, 0);
|
||||||
OnlinePlayDependencies.Client.AddUser(new APIUser { Id = userId });
|
OnlinePlayDependencies.MultiplayerClient.AddUser(new APIUser { Id = userId });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -60,8 +60,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
{
|
{
|
||||||
AddStep("start players silently", () =>
|
AddStep("start players silently", () =>
|
||||||
{
|
{
|
||||||
OnlinePlayDependencies.Client.AddUser(new APIUser { Id = PLAYER_1_ID }, true);
|
OnlinePlayDependencies.MultiplayerClient.AddUser(new APIUser { Id = PLAYER_1_ID }, true);
|
||||||
OnlinePlayDependencies.Client.AddUser(new APIUser { Id = PLAYER_2_ID }, true);
|
OnlinePlayDependencies.MultiplayerClient.AddUser(new APIUser { Id = PLAYER_2_ID }, true);
|
||||||
|
|
||||||
playingUsers.Add(new MultiplayerRoomUser(PLAYER_1_ID));
|
playingUsers.Add(new MultiplayerRoomUser(PLAYER_1_ID));
|
||||||
playingUsers.Add(new MultiplayerRoomUser(PLAYER_2_ID));
|
playingUsers.Add(new MultiplayerRoomUser(PLAYER_2_ID));
|
||||||
@ -121,13 +121,13 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
{
|
{
|
||||||
AddStep("start players", () =>
|
AddStep("start players", () =>
|
||||||
{
|
{
|
||||||
var player1 = OnlinePlayDependencies.Client.AddUser(new APIUser { Id = PLAYER_1_ID }, true);
|
var player1 = OnlinePlayDependencies.MultiplayerClient.AddUser(new APIUser { Id = PLAYER_1_ID }, true);
|
||||||
player1.MatchState = new TeamVersusUserState
|
player1.MatchState = new TeamVersusUserState
|
||||||
{
|
{
|
||||||
TeamID = 0,
|
TeamID = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
var player2 = OnlinePlayDependencies.Client.AddUser(new APIUser { Id = PLAYER_2_ID }, true);
|
var player2 = OnlinePlayDependencies.MultiplayerClient.AddUser(new APIUser { Id = PLAYER_2_ID }, true);
|
||||||
player2.MatchState = new TeamVersusUserState
|
player2.MatchState = new TeamVersusUserState
|
||||||
{
|
{
|
||||||
TeamID = 1,
|
TeamID = 1,
|
||||||
@ -396,7 +396,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
User = new APIUser { Id = id },
|
User = new APIUser { Id = id },
|
||||||
};
|
};
|
||||||
|
|
||||||
OnlinePlayDependencies.Client.AddUser(user.User, true);
|
OnlinePlayDependencies.MultiplayerClient.AddUser(user.User, true);
|
||||||
SpectatorClient.StartPlay(id, beatmapId ?? importedBeatmapId);
|
SpectatorClient.StartPlay(id, beatmapId ?? importedBeatmapId);
|
||||||
|
|
||||||
playingUsers.Add(user);
|
playingUsers.Add(user);
|
||||||
@ -410,7 +410,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
{
|
{
|
||||||
var user = playingUsers.Single(u => u.UserID == userId);
|
var user = playingUsers.Single(u => u.UserID == userId);
|
||||||
|
|
||||||
OnlinePlayDependencies.Client.RemoveUser(user.User.AsNonNull());
|
OnlinePlayDependencies.MultiplayerClient.RemoveUser(user.User.AsNonNull());
|
||||||
SpectatorClient.EndPlay(userId);
|
SpectatorClient.EndPlay(userId);
|
||||||
|
|
||||||
playingUsers.Remove(user);
|
playingUsers.Remove(user);
|
||||||
|
@ -17,8 +17,8 @@ using osu.Framework.Screens;
|
|||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
using osu.Framework.Utils;
|
using osu.Framework.Utils;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Database;
|
|
||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
using osu.Game.Online.API;
|
||||||
using osu.Game.Online.API.Requests.Responses;
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
using osu.Game.Online.Multiplayer;
|
using osu.Game.Online.Multiplayer;
|
||||||
using osu.Game.Online.Rooms;
|
using osu.Game.Online.Rooms;
|
||||||
@ -52,12 +52,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
|
|
||||||
private TestMultiplayerComponents multiplayerComponents;
|
private TestMultiplayerComponents multiplayerComponents;
|
||||||
|
|
||||||
private TestMultiplayerClient client => multiplayerComponents.Client;
|
private TestMultiplayerClient multiplayerClient => multiplayerComponents.MultiplayerClient;
|
||||||
private TestMultiplayerRoomManager roomManager => multiplayerComponents.RoomManager;
|
private TestMultiplayerRoomManager roomManager => multiplayerComponents.RoomManager;
|
||||||
|
|
||||||
[Cached(typeof(UserLookupCache))]
|
|
||||||
private UserLookupCache lookupCache = new TestUserLookupCache();
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(GameHost host, AudioManager audio)
|
private void load(GameHost host, AudioManager audio)
|
||||||
{
|
{
|
||||||
@ -96,10 +93,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
Name = { Value = "Test Room" },
|
Name = { Value = "Test Room" },
|
||||||
Playlist =
|
Playlist =
|
||||||
{
|
{
|
||||||
new PlaylistItem
|
new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
|
||||||
{
|
{
|
||||||
Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
|
||||||
Ruleset = { Value = new OsuRuleset().RulesetInfo },
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -112,66 +108,66 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
// all ready
|
// all ready
|
||||||
AddUntilStep("all players ready", () =>
|
AddUntilStep("all players ready", () =>
|
||||||
{
|
{
|
||||||
var nextUnready = client.Room?.Users.FirstOrDefault(c => c.State == MultiplayerUserState.Idle);
|
var nextUnready = multiplayerClient.Room?.Users.FirstOrDefault(c => c.State == MultiplayerUserState.Idle);
|
||||||
if (nextUnready != null)
|
if (nextUnready != null)
|
||||||
client.ChangeUserState(nextUnready.UserID, MultiplayerUserState.Ready);
|
multiplayerClient.ChangeUserState(nextUnready.UserID, MultiplayerUserState.Ready);
|
||||||
|
|
||||||
return client.Room?.Users.All(u => u.State == MultiplayerUserState.Ready) == true;
|
return multiplayerClient.Room?.Users.All(u => u.State == MultiplayerUserState.Ready) == true;
|
||||||
});
|
});
|
||||||
|
|
||||||
AddStep("unready all players at once", () =>
|
AddStep("unready all players at once", () =>
|
||||||
{
|
{
|
||||||
Debug.Assert(client.Room != null);
|
Debug.Assert(multiplayerClient.Room != null);
|
||||||
|
|
||||||
foreach (var u in client.Room.Users) client.ChangeUserState(u.UserID, MultiplayerUserState.Idle);
|
foreach (var u in multiplayerClient.Room.Users) multiplayerClient.ChangeUserState(u.UserID, MultiplayerUserState.Idle);
|
||||||
});
|
});
|
||||||
|
|
||||||
AddStep("ready all players at once", () =>
|
AddStep("ready all players at once", () =>
|
||||||
{
|
{
|
||||||
Debug.Assert(client.Room != null);
|
Debug.Assert(multiplayerClient.Room != null);
|
||||||
|
|
||||||
foreach (var u in client.Room.Users) client.ChangeUserState(u.UserID, MultiplayerUserState.Ready);
|
foreach (var u in multiplayerClient.Room.Users) multiplayerClient.ChangeUserState(u.UserID, MultiplayerUserState.Ready);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addRandomPlayer()
|
private void addRandomPlayer()
|
||||||
{
|
{
|
||||||
int randomUser = RNG.Next(200000, 500000);
|
int randomUser = RNG.Next(200000, 500000);
|
||||||
client.AddUser(new APIUser { Id = randomUser, Username = $"user {randomUser}" });
|
multiplayerClient.AddUser(new APIUser { Id = randomUser, Username = $"user {randomUser}" });
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeLastUser()
|
private void removeLastUser()
|
||||||
{
|
{
|
||||||
APIUser lastUser = client.Room?.Users.Last().User;
|
APIUser lastUser = multiplayerClient.Room?.Users.Last().User;
|
||||||
|
|
||||||
if (lastUser == null || lastUser == client.LocalUser?.User)
|
if (lastUser == null || lastUser == multiplayerClient.LocalUser?.User)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
client.RemoveUser(lastUser);
|
multiplayerClient.RemoveUser(lastUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void kickLastUser()
|
private void kickLastUser()
|
||||||
{
|
{
|
||||||
APIUser lastUser = client.Room?.Users.Last().User;
|
APIUser lastUser = multiplayerClient.Room?.Users.Last().User;
|
||||||
|
|
||||||
if (lastUser == null || lastUser == client.LocalUser?.User)
|
if (lastUser == null || lastUser == multiplayerClient.LocalUser?.User)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
client.KickUser(lastUser.Id);
|
multiplayerClient.KickUser(lastUser.Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void markNextPlayerReady()
|
private void markNextPlayerReady()
|
||||||
{
|
{
|
||||||
var nextUnready = client.Room?.Users.FirstOrDefault(c => c.State == MultiplayerUserState.Idle);
|
var nextUnready = multiplayerClient.Room?.Users.FirstOrDefault(c => c.State == MultiplayerUserState.Idle);
|
||||||
if (nextUnready != null)
|
if (nextUnready != null)
|
||||||
client.ChangeUserState(nextUnready.UserID, MultiplayerUserState.Ready);
|
multiplayerClient.ChangeUserState(nextUnready.UserID, MultiplayerUserState.Ready);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void markNextPlayerIdle()
|
private void markNextPlayerIdle()
|
||||||
{
|
{
|
||||||
var nextUnready = client.Room?.Users.FirstOrDefault(c => c.State == MultiplayerUserState.Ready);
|
var nextUnready = multiplayerClient.Room?.Users.FirstOrDefault(c => c.State == MultiplayerUserState.Ready);
|
||||||
if (nextUnready != null)
|
if (nextUnready != null)
|
||||||
client.ChangeUserState(nextUnready.UserID, MultiplayerUserState.Idle);
|
multiplayerClient.ChangeUserState(nextUnready.UserID, MultiplayerUserState.Idle);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void performRandomAction()
|
private void performRandomAction()
|
||||||
@ -221,7 +217,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
AddStep("Press select", () => InputManager.Key(Key.Enter));
|
AddStep("Press select", () => InputManager.Key(Key.Enter));
|
||||||
|
|
||||||
AddUntilStep("wait for room open", () => this.ChildrenOfType<MultiplayerMatchSubScreen>().FirstOrDefault()?.IsLoaded == true);
|
AddUntilStep("wait for room open", () => this.ChildrenOfType<MultiplayerMatchSubScreen>().FirstOrDefault()?.IsLoaded == true);
|
||||||
AddUntilStep("wait for join", () => client.RoomJoined);
|
AddUntilStep("wait for join", () => multiplayerClient.RoomJoined);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -232,16 +228,15 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
Name = { Value = "Test Room" },
|
Name = { Value = "Test Room" },
|
||||||
Playlist =
|
Playlist =
|
||||||
{
|
{
|
||||||
new PlaylistItem
|
new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
|
||||||
{
|
{
|
||||||
Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
|
||||||
Ruleset = { Value = new OsuRuleset().RulesetInfo },
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
AddAssert("Check participant count correct", () => client.APIRoom?.ParticipantCount.Value == 1);
|
AddAssert("Check participant count correct", () => multiplayerClient.APIRoom?.ParticipantCount.Value == 1);
|
||||||
AddAssert("Check participant list contains user", () => client.APIRoom?.RecentParticipants.Count(u => u.Id == API.LocalUser.Value.Id) == 1);
|
AddAssert("Check participant list contains user", () => multiplayerClient.APIRoom?.RecentParticipants.Count(u => u.Id == API.LocalUser.Value.Id) == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -254,10 +249,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
Name = { Value = "Test Room" },
|
Name = { Value = "Test Room" },
|
||||||
Playlist =
|
Playlist =
|
||||||
{
|
{
|
||||||
new PlaylistItem
|
new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
|
||||||
{
|
{
|
||||||
Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
|
||||||
Ruleset = { Value = new OsuRuleset().RulesetInfo },
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, API.LocalUser.Value);
|
}, API.LocalUser.Value);
|
||||||
@ -284,10 +278,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
Name = { Value = "Test Room" },
|
Name = { Value = "Test Room" },
|
||||||
Playlist =
|
Playlist =
|
||||||
{
|
{
|
||||||
new PlaylistItem
|
new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
|
||||||
{
|
{
|
||||||
Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
|
||||||
Ruleset = { Value = new OsuRuleset().RulesetInfo },
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, API.LocalUser.Value);
|
}, API.LocalUser.Value);
|
||||||
@ -300,10 +293,10 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
AddStep("join room", () => InputManager.Key(Key.Enter));
|
AddStep("join room", () => InputManager.Key(Key.Enter));
|
||||||
|
|
||||||
AddUntilStep("wait for room open", () => this.ChildrenOfType<MultiplayerMatchSubScreen>().FirstOrDefault()?.IsLoaded == true);
|
AddUntilStep("wait for room open", () => this.ChildrenOfType<MultiplayerMatchSubScreen>().FirstOrDefault()?.IsLoaded == true);
|
||||||
AddUntilStep("wait for join", () => client.RoomJoined);
|
AddUntilStep("wait for join", () => multiplayerClient.RoomJoined);
|
||||||
|
|
||||||
AddAssert("Check participant count correct", () => client.APIRoom?.ParticipantCount.Value == 1);
|
AddAssert("Check participant count correct", () => multiplayerClient.APIRoom?.ParticipantCount.Value == 1);
|
||||||
AddAssert("Check participant list contains user", () => client.APIRoom?.RecentParticipants.Count(u => u.Id == API.LocalUser.Value.Id) == 1);
|
AddAssert("Check participant list contains user", () => multiplayerClient.APIRoom?.RecentParticipants.Count(u => u.Id == API.LocalUser.Value.Id) == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -315,15 +308,14 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
Password = { Value = "password" },
|
Password = { Value = "password" },
|
||||||
Playlist =
|
Playlist =
|
||||||
{
|
{
|
||||||
new PlaylistItem
|
new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
|
||||||
{
|
{
|
||||||
Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
|
||||||
Ruleset = { Value = new OsuRuleset().RulesetInfo },
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
AddAssert("room has password", () => client.APIRoom?.Password.Value == "password");
|
AddAssert("room has password", () => multiplayerClient.APIRoom?.Password.Value == "password");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -337,10 +329,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
Password = { Value = "password" },
|
Password = { Value = "password" },
|
||||||
Playlist =
|
Playlist =
|
||||||
{
|
{
|
||||||
new PlaylistItem
|
new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
|
||||||
{
|
{
|
||||||
Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
|
||||||
Ruleset = { Value = new OsuRuleset().RulesetInfo },
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, API.LocalUser.Value);
|
}, API.LocalUser.Value);
|
||||||
@ -358,7 +349,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
AddStep("press join room button", () => passwordEntryPopover.ChildrenOfType<OsuButton>().First().TriggerClick());
|
AddStep("press join room button", () => passwordEntryPopover.ChildrenOfType<OsuButton>().First().TriggerClick());
|
||||||
|
|
||||||
AddUntilStep("wait for room open", () => this.ChildrenOfType<MultiplayerMatchSubScreen>().FirstOrDefault()?.IsLoaded == true);
|
AddUntilStep("wait for room open", () => this.ChildrenOfType<MultiplayerMatchSubScreen>().FirstOrDefault()?.IsLoaded == true);
|
||||||
AddUntilStep("wait for join", () => client.RoomJoined);
|
AddUntilStep("wait for join", () => multiplayerClient.RoomJoined);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -370,16 +361,15 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
Password = { Value = "password" },
|
Password = { Value = "password" },
|
||||||
Playlist =
|
Playlist =
|
||||||
{
|
{
|
||||||
new PlaylistItem
|
new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
|
||||||
{
|
{
|
||||||
Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
|
||||||
Ruleset = { Value = new OsuRuleset().RulesetInfo },
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
AddStep("change password", () => client.ChangeSettings(password: "password2"));
|
AddStep("change password", () => multiplayerClient.ChangeSettings(password: "password2"));
|
||||||
AddUntilStep("local password changed", () => client.APIRoom?.Password.Value == "password2");
|
AddUntilStep("local password changed", () => multiplayerClient.APIRoom?.Password.Value == "password2");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -390,10 +380,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
Name = { Value = "Test Room" },
|
Name = { Value = "Test Room" },
|
||||||
Playlist =
|
Playlist =
|
||||||
{
|
{
|
||||||
new PlaylistItem
|
new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
|
||||||
{
|
{
|
||||||
Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
|
||||||
Ruleset = { Value = new OsuRuleset().RulesetInfo },
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -401,7 +390,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
pressReadyButton();
|
pressReadyButton();
|
||||||
|
|
||||||
AddStep("delete beatmap", () => beatmaps.Delete(importedSet));
|
AddStep("delete beatmap", () => beatmaps.Delete(importedSet));
|
||||||
AddUntilStep("user state is idle", () => client.LocalUser?.State == MultiplayerUserState.Idle);
|
AddUntilStep("user state is idle", () => multiplayerClient.LocalUser?.State == MultiplayerUserState.Idle);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -412,10 +401,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
Name = { Value = "Test Room" },
|
Name = { Value = "Test Room" },
|
||||||
Playlist =
|
Playlist =
|
||||||
{
|
{
|
||||||
new PlaylistItem
|
new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
|
||||||
{
|
{
|
||||||
Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
|
||||||
Ruleset = { Value = new OsuRuleset().RulesetInfo },
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -425,22 +413,22 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
AddStep("Enter song select", () =>
|
AddStep("Enter song select", () =>
|
||||||
{
|
{
|
||||||
var currentSubScreen = ((Screens.OnlinePlay.Multiplayer.Multiplayer)multiplayerComponents.CurrentScreen).CurrentSubScreen;
|
var currentSubScreen = ((Screens.OnlinePlay.Multiplayer.Multiplayer)multiplayerComponents.CurrentScreen).CurrentSubScreen;
|
||||||
((MultiplayerMatchSubScreen)currentSubScreen).OpenSongSelection(client.Room?.Settings.PlaylistItemId);
|
((MultiplayerMatchSubScreen)currentSubScreen).OpenSongSelection(multiplayerClient.Room?.Settings.PlaylistItemId);
|
||||||
});
|
});
|
||||||
|
|
||||||
AddUntilStep("wait for song select", () => this.ChildrenOfType<MultiplayerMatchSongSelect>().FirstOrDefault()?.BeatmapSetsLoaded == true);
|
AddUntilStep("wait for song select", () => this.ChildrenOfType<MultiplayerMatchSongSelect>().FirstOrDefault()?.BeatmapSetsLoaded == true);
|
||||||
|
|
||||||
AddAssert("Beatmap matches current item", () => Beatmap.Value.BeatmapInfo.OnlineID == client.Room?.Playlist.First().BeatmapID);
|
AddAssert("Beatmap matches current item", () => Beatmap.Value.BeatmapInfo.OnlineID == multiplayerClient.Room?.Playlist.First().BeatmapID);
|
||||||
|
|
||||||
AddStep("Select next beatmap", () => InputManager.Key(Key.Down));
|
AddStep("Select next beatmap", () => InputManager.Key(Key.Down));
|
||||||
|
|
||||||
AddUntilStep("Beatmap doesn't match current item", () => Beatmap.Value.BeatmapInfo.OnlineID != client.Room?.Playlist.First().BeatmapID);
|
AddUntilStep("Beatmap doesn't match current item", () => Beatmap.Value.BeatmapInfo.OnlineID != multiplayerClient.Room?.Playlist.First().BeatmapID);
|
||||||
|
|
||||||
AddStep("start match externally", () => client.StartMatch());
|
AddStep("start match externally", () => multiplayerClient.StartMatch());
|
||||||
|
|
||||||
AddUntilStep("play started", () => multiplayerComponents.CurrentScreen is Player);
|
AddUntilStep("play started", () => multiplayerComponents.CurrentScreen is Player);
|
||||||
|
|
||||||
AddAssert("Beatmap matches current item", () => Beatmap.Value.BeatmapInfo.OnlineID == client.Room?.Playlist.First().BeatmapID);
|
AddAssert("Beatmap matches current item", () => Beatmap.Value.BeatmapInfo.OnlineID == multiplayerClient.Room?.Playlist.First().BeatmapID);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -451,10 +439,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
Name = { Value = "Test Room" },
|
Name = { Value = "Test Room" },
|
||||||
Playlist =
|
Playlist =
|
||||||
{
|
{
|
||||||
new PlaylistItem
|
new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
|
||||||
{
|
{
|
||||||
Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
|
||||||
Ruleset = { Value = new OsuRuleset().RulesetInfo },
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -464,22 +451,22 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
AddStep("Enter song select", () =>
|
AddStep("Enter song select", () =>
|
||||||
{
|
{
|
||||||
var currentSubScreen = ((Screens.OnlinePlay.Multiplayer.Multiplayer)multiplayerComponents.CurrentScreen).CurrentSubScreen;
|
var currentSubScreen = ((Screens.OnlinePlay.Multiplayer.Multiplayer)multiplayerComponents.CurrentScreen).CurrentSubScreen;
|
||||||
((MultiplayerMatchSubScreen)currentSubScreen).OpenSongSelection(client.Room?.Settings.PlaylistItemId);
|
((MultiplayerMatchSubScreen)currentSubScreen).OpenSongSelection(multiplayerClient.Room?.Settings.PlaylistItemId);
|
||||||
});
|
});
|
||||||
|
|
||||||
AddUntilStep("wait for song select", () => this.ChildrenOfType<MultiplayerMatchSongSelect>().FirstOrDefault()?.BeatmapSetsLoaded == true);
|
AddUntilStep("wait for song select", () => this.ChildrenOfType<MultiplayerMatchSongSelect>().FirstOrDefault()?.BeatmapSetsLoaded == true);
|
||||||
|
|
||||||
AddAssert("Ruleset matches current item", () => Ruleset.Value.OnlineID == client.Room?.Playlist.First().RulesetID);
|
AddAssert("Ruleset matches current item", () => Ruleset.Value.OnlineID == multiplayerClient.Room?.Playlist.First().RulesetID);
|
||||||
|
|
||||||
AddStep("Switch ruleset", () => ((MultiplayerMatchSongSelect)multiplayerComponents.MultiplayerScreen.CurrentSubScreen).Ruleset.Value = new CatchRuleset().RulesetInfo);
|
AddStep("Switch ruleset", () => ((MultiplayerMatchSongSelect)multiplayerComponents.MultiplayerScreen.CurrentSubScreen).Ruleset.Value = new CatchRuleset().RulesetInfo);
|
||||||
|
|
||||||
AddUntilStep("Ruleset doesn't match current item", () => Ruleset.Value.OnlineID != client.Room?.Playlist.First().RulesetID);
|
AddUntilStep("Ruleset doesn't match current item", () => Ruleset.Value.OnlineID != multiplayerClient.Room?.Playlist.First().RulesetID);
|
||||||
|
|
||||||
AddStep("start match externally", () => client.StartMatch());
|
AddStep("start match externally", () => multiplayerClient.StartMatch());
|
||||||
|
|
||||||
AddUntilStep("play started", () => multiplayerComponents.CurrentScreen is Player);
|
AddUntilStep("play started", () => multiplayerComponents.CurrentScreen is Player);
|
||||||
|
|
||||||
AddAssert("Ruleset matches current item", () => Ruleset.Value.OnlineID == client.Room?.Playlist.First().RulesetID);
|
AddAssert("Ruleset matches current item", () => Ruleset.Value.OnlineID == multiplayerClient.Room?.Playlist.First().RulesetID);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -490,10 +477,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
Name = { Value = "Test Room" },
|
Name = { Value = "Test Room" },
|
||||||
Playlist =
|
Playlist =
|
||||||
{
|
{
|
||||||
new PlaylistItem
|
new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
|
||||||
{
|
{
|
||||||
Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
|
||||||
Ruleset = { Value = new OsuRuleset().RulesetInfo },
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -503,22 +489,22 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
AddStep("Enter song select", () =>
|
AddStep("Enter song select", () =>
|
||||||
{
|
{
|
||||||
var currentSubScreen = ((Screens.OnlinePlay.Multiplayer.Multiplayer)multiplayerComponents.CurrentScreen).CurrentSubScreen;
|
var currentSubScreen = ((Screens.OnlinePlay.Multiplayer.Multiplayer)multiplayerComponents.CurrentScreen).CurrentSubScreen;
|
||||||
((MultiplayerMatchSubScreen)currentSubScreen).OpenSongSelection(client.Room?.Settings.PlaylistItemId);
|
((MultiplayerMatchSubScreen)currentSubScreen).OpenSongSelection(multiplayerClient.Room?.Settings.PlaylistItemId);
|
||||||
});
|
});
|
||||||
|
|
||||||
AddUntilStep("wait for song select", () => this.ChildrenOfType<MultiplayerMatchSongSelect>().FirstOrDefault()?.BeatmapSetsLoaded == true);
|
AddUntilStep("wait for song select", () => this.ChildrenOfType<MultiplayerMatchSongSelect>().FirstOrDefault()?.BeatmapSetsLoaded == true);
|
||||||
|
|
||||||
AddAssert("Mods match current item", () => SelectedMods.Value.Select(m => m.Acronym).SequenceEqual(client.Room.AsNonNull().Playlist.First().RequiredMods.Select(m => m.Acronym)));
|
AddAssert("Mods match current item", () => SelectedMods.Value.Select(m => m.Acronym).SequenceEqual(multiplayerClient.Room.AsNonNull().Playlist.First().RequiredMods.Select(m => m.Acronym)));
|
||||||
|
|
||||||
AddStep("Switch required mods", () => ((MultiplayerMatchSongSelect)multiplayerComponents.MultiplayerScreen.CurrentSubScreen).Mods.Value = new Mod[] { new OsuModDoubleTime() });
|
AddStep("Switch required mods", () => ((MultiplayerMatchSongSelect)multiplayerComponents.MultiplayerScreen.CurrentSubScreen).Mods.Value = new Mod[] { new OsuModDoubleTime() });
|
||||||
|
|
||||||
AddAssert("Mods don't match current item", () => !SelectedMods.Value.Select(m => m.Acronym).SequenceEqual(client.Room.AsNonNull().Playlist.First().RequiredMods.Select(m => m.Acronym)));
|
AddAssert("Mods don't match current item", () => !SelectedMods.Value.Select(m => m.Acronym).SequenceEqual(multiplayerClient.Room.AsNonNull().Playlist.First().RequiredMods.Select(m => m.Acronym)));
|
||||||
|
|
||||||
AddStep("start match externally", () => client.StartMatch());
|
AddStep("start match externally", () => multiplayerClient.StartMatch());
|
||||||
|
|
||||||
AddUntilStep("play started", () => multiplayerComponents.CurrentScreen is Player);
|
AddUntilStep("play started", () => multiplayerComponents.CurrentScreen is Player);
|
||||||
|
|
||||||
AddAssert("Mods match current item", () => SelectedMods.Value.Select(m => m.Acronym).SequenceEqual(client.Room.AsNonNull().Playlist.First().RequiredMods.Select(m => m.Acronym)));
|
AddAssert("Mods match current item", () => SelectedMods.Value.Select(m => m.Acronym).SequenceEqual(multiplayerClient.Room.AsNonNull().Playlist.First().RequiredMods.Select(m => m.Acronym)));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -529,28 +515,27 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
Name = { Value = "Test Room" },
|
Name = { Value = "Test Room" },
|
||||||
Playlist =
|
Playlist =
|
||||||
{
|
{
|
||||||
new PlaylistItem
|
new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
|
||||||
{
|
{
|
||||||
Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
|
||||||
Ruleset = { Value = new OsuRuleset().RulesetInfo },
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
AddStep("join other user (ready, host)", () =>
|
AddStep("join other user (ready, host)", () =>
|
||||||
{
|
{
|
||||||
client.AddUser(new APIUser { Id = MultiplayerTestScene.PLAYER_1_ID, Username = "Other" });
|
multiplayerClient.AddUser(new APIUser { Id = MultiplayerTestScene.PLAYER_1_ID, Username = "Other" });
|
||||||
client.TransferHost(MultiplayerTestScene.PLAYER_1_ID);
|
multiplayerClient.TransferHost(MultiplayerTestScene.PLAYER_1_ID);
|
||||||
client.ChangeUserState(MultiplayerTestScene.PLAYER_1_ID, MultiplayerUserState.Ready);
|
multiplayerClient.ChangeUserState(MultiplayerTestScene.PLAYER_1_ID, MultiplayerUserState.Ready);
|
||||||
});
|
});
|
||||||
|
|
||||||
AddStep("delete beatmap", () => beatmaps.Delete(importedSet));
|
AddStep("delete beatmap", () => beatmaps.Delete(importedSet));
|
||||||
|
|
||||||
ClickButtonWhenEnabled<MultiplayerSpectateButton>();
|
ClickButtonWhenEnabled<MultiplayerSpectateButton>();
|
||||||
|
|
||||||
AddUntilStep("wait for spectating user state", () => client.LocalUser?.State == MultiplayerUserState.Spectating);
|
AddUntilStep("wait for spectating user state", () => multiplayerClient.LocalUser?.State == MultiplayerUserState.Spectating);
|
||||||
|
|
||||||
AddStep("start match externally", () => client.StartMatch());
|
AddStep("start match externally", () => multiplayerClient.StartMatch());
|
||||||
|
|
||||||
AddAssert("play not started", () => multiplayerComponents.IsCurrentScreen());
|
AddAssert("play not started", () => multiplayerComponents.IsCurrentScreen());
|
||||||
}
|
}
|
||||||
@ -563,10 +548,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
Name = { Value = "Test Room" },
|
Name = { Value = "Test Room" },
|
||||||
Playlist =
|
Playlist =
|
||||||
{
|
{
|
||||||
new PlaylistItem
|
new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
|
||||||
{
|
{
|
||||||
Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
|
||||||
Ruleset = { Value = new OsuRuleset().RulesetInfo },
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -575,16 +559,16 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
|
|
||||||
AddStep("join other user (ready, host)", () =>
|
AddStep("join other user (ready, host)", () =>
|
||||||
{
|
{
|
||||||
client.AddUser(new APIUser { Id = MultiplayerTestScene.PLAYER_1_ID, Username = "Other" });
|
multiplayerClient.AddUser(new APIUser { Id = MultiplayerTestScene.PLAYER_1_ID, Username = "Other" });
|
||||||
client.TransferHost(MultiplayerTestScene.PLAYER_1_ID);
|
multiplayerClient.TransferHost(MultiplayerTestScene.PLAYER_1_ID);
|
||||||
client.ChangeUserState(MultiplayerTestScene.PLAYER_1_ID, MultiplayerUserState.Ready);
|
multiplayerClient.ChangeUserState(MultiplayerTestScene.PLAYER_1_ID, MultiplayerUserState.Ready);
|
||||||
});
|
});
|
||||||
|
|
||||||
ClickButtonWhenEnabled<MultiplayerSpectateButton>();
|
ClickButtonWhenEnabled<MultiplayerSpectateButton>();
|
||||||
|
|
||||||
AddUntilStep("wait for spectating user state", () => client.LocalUser?.State == MultiplayerUserState.Spectating);
|
AddUntilStep("wait for spectating user state", () => multiplayerClient.LocalUser?.State == MultiplayerUserState.Spectating);
|
||||||
|
|
||||||
AddStep("start match externally", () => client.StartMatch());
|
AddStep("start match externally", () => multiplayerClient.StartMatch());
|
||||||
|
|
||||||
AddStep("restore beatmap", () =>
|
AddStep("restore beatmap", () =>
|
||||||
{
|
{
|
||||||
@ -603,15 +587,14 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
Name = { Value = "Test Room" },
|
Name = { Value = "Test Room" },
|
||||||
Playlist =
|
Playlist =
|
||||||
{
|
{
|
||||||
new PlaylistItem
|
new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
|
||||||
{
|
{
|
||||||
Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
|
||||||
Ruleset = { Value = new OsuRuleset().RulesetInfo },
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
AddStep("disconnect", () => client.Disconnect());
|
AddStep("disconnect", () => multiplayerClient.Disconnect());
|
||||||
AddUntilStep("back in lounge", () => this.ChildrenOfType<LoungeSubScreen>().FirstOrDefault()?.IsCurrentScreen() == true);
|
AddUntilStep("back in lounge", () => this.ChildrenOfType<LoungeSubScreen>().FirstOrDefault()?.IsCurrentScreen() == true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -623,11 +606,10 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
Name = { Value = "Test Room" },
|
Name = { Value = "Test Room" },
|
||||||
Playlist =
|
Playlist =
|
||||||
{
|
{
|
||||||
new PlaylistItem
|
new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
|
||||||
{
|
{
|
||||||
Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID,
|
||||||
Ruleset = { Value = new OsuRuleset().RulesetInfo },
|
AllowedMods = new[] { new APIMod(new OsuModHidden()) }
|
||||||
AllowedMods = { new OsuModHidden() }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -663,10 +645,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
Name = { Value = "Test Room" },
|
Name = { Value = "Test Room" },
|
||||||
Playlist =
|
Playlist =
|
||||||
{
|
{
|
||||||
new PlaylistItem
|
new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
|
||||||
{
|
{
|
||||||
Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID,
|
||||||
Ruleset = { Value = new OsuRuleset().RulesetInfo },
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -694,10 +675,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
QueueMode = { Value = QueueMode.AllPlayers },
|
QueueMode = { Value = QueueMode.AllPlayers },
|
||||||
Playlist =
|
Playlist =
|
||||||
{
|
{
|
||||||
new PlaylistItem
|
new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
|
||||||
{
|
{
|
||||||
Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID,
|
||||||
Ruleset = { Value = new OsuRuleset().RulesetInfo },
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, API.LocalUser.Value);
|
}, API.LocalUser.Value);
|
||||||
@ -711,17 +691,16 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
AddStep("change server-side settings", () =>
|
AddStep("change server-side settings", () =>
|
||||||
{
|
{
|
||||||
roomManager.ServerSideRooms[0].Name.Value = "New name";
|
roomManager.ServerSideRooms[0].Name.Value = "New name";
|
||||||
roomManager.ServerSideRooms[0].Playlist.Add(new PlaylistItem
|
roomManager.ServerSideRooms[0].Playlist.Add(new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
|
||||||
{
|
{
|
||||||
ID = 2,
|
ID = 2,
|
||||||
Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID,
|
||||||
Ruleset = { Value = new OsuRuleset().RulesetInfo },
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
AddStep("join room", () => InputManager.Key(Key.Enter));
|
AddStep("join room", () => InputManager.Key(Key.Enter));
|
||||||
AddUntilStep("wait for room open", () => this.ChildrenOfType<MultiplayerMatchSubScreen>().FirstOrDefault()?.IsLoaded == true);
|
AddUntilStep("wait for room open", () => this.ChildrenOfType<MultiplayerMatchSubScreen>().FirstOrDefault()?.IsLoaded == true);
|
||||||
AddUntilStep("wait for join", () => client.RoomJoined);
|
AddUntilStep("wait for join", () => multiplayerClient.RoomJoined);
|
||||||
|
|
||||||
AddAssert("local room has correct settings", () =>
|
AddAssert("local room has correct settings", () =>
|
||||||
{
|
{
|
||||||
@ -740,19 +719,18 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
QueueMode = { Value = QueueMode.AllPlayers },
|
QueueMode = { Value = QueueMode.AllPlayers },
|
||||||
Playlist =
|
Playlist =
|
||||||
{
|
{
|
||||||
new PlaylistItem
|
new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
|
||||||
{
|
{
|
||||||
Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID,
|
||||||
Ruleset = { Value = new OsuRuleset().RulesetInfo },
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
AddStep("set spectating state", () => client.ChangeUserState(API.LocalUser.Value.OnlineID, MultiplayerUserState.Spectating));
|
AddStep("set spectating state", () => multiplayerClient.ChangeUserState(API.LocalUser.Value.OnlineID, MultiplayerUserState.Spectating));
|
||||||
AddUntilStep("state set to spectating", () => client.LocalUser?.State == MultiplayerUserState.Spectating);
|
AddUntilStep("state set to spectating", () => multiplayerClient.LocalUser?.State == MultiplayerUserState.Spectating);
|
||||||
|
|
||||||
AddStep("join other user", () => client.AddUser(new APIUser { Id = 1234 }));
|
AddStep("join other user", () => multiplayerClient.AddUser(new APIUser { Id = 1234 }));
|
||||||
AddStep("set other user ready", () => client.ChangeUserState(1234, MultiplayerUserState.Ready));
|
AddStep("set other user ready", () => multiplayerClient.ChangeUserState(1234, MultiplayerUserState.Ready));
|
||||||
|
|
||||||
pressReadyButton(1234);
|
pressReadyButton(1234);
|
||||||
AddUntilStep("wait for gameplay", () => (multiplayerComponents.CurrentScreen as MultiSpectatorScreen)?.IsLoaded == true);
|
AddUntilStep("wait for gameplay", () => (multiplayerComponents.CurrentScreen as MultiSpectatorScreen)?.IsLoaded == true);
|
||||||
@ -764,7 +742,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
});
|
});
|
||||||
|
|
||||||
AddUntilStep("wait for return to match subscreen", () => multiplayerComponents.MultiplayerScreen.IsCurrentScreen());
|
AddUntilStep("wait for return to match subscreen", () => multiplayerComponents.MultiplayerScreen.IsCurrentScreen());
|
||||||
AddUntilStep("user state is idle", () => client.LocalUser?.State == MultiplayerUserState.Idle);
|
AddUntilStep("user state is idle", () => multiplayerClient.LocalUser?.State == MultiplayerUserState.Idle);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -776,24 +754,23 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
QueueMode = { Value = QueueMode.AllPlayers },
|
QueueMode = { Value = QueueMode.AllPlayers },
|
||||||
Playlist =
|
Playlist =
|
||||||
{
|
{
|
||||||
new PlaylistItem
|
new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
|
||||||
{
|
{
|
||||||
Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID,
|
||||||
Ruleset = { Value = new OsuRuleset().RulesetInfo },
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
AddStep("set spectating state", () => client.ChangeUserState(API.LocalUser.Value.OnlineID, MultiplayerUserState.Spectating));
|
AddStep("set spectating state", () => multiplayerClient.ChangeUserState(API.LocalUser.Value.OnlineID, MultiplayerUserState.Spectating));
|
||||||
AddUntilStep("state set to spectating", () => client.LocalUser?.State == MultiplayerUserState.Spectating);
|
AddUntilStep("state set to spectating", () => multiplayerClient.LocalUser?.State == MultiplayerUserState.Spectating);
|
||||||
|
|
||||||
AddStep("join other user", () => client.AddUser(new APIUser { Id = 1234 }));
|
AddStep("join other user", () => multiplayerClient.AddUser(new APIUser { Id = 1234 }));
|
||||||
AddStep("set other user ready", () => client.ChangeUserState(1234, MultiplayerUserState.Ready));
|
AddStep("set other user ready", () => multiplayerClient.ChangeUserState(1234, MultiplayerUserState.Ready));
|
||||||
|
|
||||||
pressReadyButton(1234);
|
pressReadyButton(1234);
|
||||||
AddUntilStep("wait for gameplay", () => (multiplayerComponents.CurrentScreen as MultiSpectatorScreen)?.IsLoaded == true);
|
AddUntilStep("wait for gameplay", () => (multiplayerComponents.CurrentScreen as MultiSpectatorScreen)?.IsLoaded == true);
|
||||||
AddStep("set other user loaded", () => client.ChangeUserState(1234, MultiplayerUserState.Loaded));
|
AddStep("set other user loaded", () => multiplayerClient.ChangeUserState(1234, MultiplayerUserState.Loaded));
|
||||||
AddStep("set other user finished play", () => client.ChangeUserState(1234, MultiplayerUserState.FinishedPlay));
|
AddStep("set other user finished play", () => multiplayerClient.ChangeUserState(1234, MultiplayerUserState.FinishedPlay));
|
||||||
|
|
||||||
AddStep("press back button and exit", () =>
|
AddStep("press back button and exit", () =>
|
||||||
{
|
{
|
||||||
@ -803,7 +780,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
|
|
||||||
AddUntilStep("wait for return to match subscreen", () => multiplayerComponents.MultiplayerScreen.IsCurrentScreen());
|
AddUntilStep("wait for return to match subscreen", () => multiplayerComponents.MultiplayerScreen.IsCurrentScreen());
|
||||||
AddWaitStep("wait for possible state change", 5);
|
AddWaitStep("wait for possible state change", 5);
|
||||||
AddUntilStep("user state is spectating", () => client.LocalUser?.State == MultiplayerUserState.Spectating);
|
AddUntilStep("user state is spectating", () => multiplayerClient.LocalUser?.State == MultiplayerUserState.Spectating);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -815,23 +792,22 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
QueueMode = { Value = QueueMode.AllPlayers },
|
QueueMode = { Value = QueueMode.AllPlayers },
|
||||||
Playlist =
|
Playlist =
|
||||||
{
|
{
|
||||||
new PlaylistItem
|
new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
|
||||||
{
|
{
|
||||||
Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID,
|
||||||
Ruleset = { Value = new OsuRuleset().RulesetInfo },
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
enterGameplay();
|
enterGameplay();
|
||||||
|
AddStep("join other user", () => multiplayerClient.AddUser(new APIUser { Id = 1234 }));
|
||||||
|
AddStep("add item as other user", () => multiplayerClient.AddUserPlaylistItem(1234, new MultiplayerPlaylistItem(
|
||||||
|
new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
|
||||||
|
{
|
||||||
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID,
|
||||||
|
})).WaitSafely());
|
||||||
|
|
||||||
AddStep("join other user", () => client.AddUser(new APIUser { Id = 1234 }));
|
AddUntilStep("item arrived in playlist", () => multiplayerClient.Room?.Playlist.Count == 2);
|
||||||
AddStep("add item as other user", () => client.AddUserPlaylistItem(1234, new MultiplayerPlaylistItem(new PlaylistItem
|
|
||||||
{
|
|
||||||
BeatmapID = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo.OnlineID
|
|
||||||
})));
|
|
||||||
|
|
||||||
AddUntilStep("item arrived in playlist", () => client.Room?.Playlist.Count == 2);
|
|
||||||
|
|
||||||
AddStep("exit gameplay as initial user", () => multiplayerComponents.MultiplayerScreen.MakeCurrent());
|
AddStep("exit gameplay as initial user", () => multiplayerComponents.MultiplayerScreen.MakeCurrent());
|
||||||
AddUntilStep("queue contains item", () => this.ChildrenOfType<MultiplayerQueueList>().Single().Items.Single().ID == 2);
|
AddUntilStep("queue contains item", () => this.ChildrenOfType<MultiplayerQueueList>().Single().Items.Single().ID == 2);
|
||||||
@ -846,26 +822,26 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
QueueMode = { Value = QueueMode.AllPlayers },
|
QueueMode = { Value = QueueMode.AllPlayers },
|
||||||
Playlist =
|
Playlist =
|
||||||
{
|
{
|
||||||
new PlaylistItem
|
new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
|
||||||
{
|
{
|
||||||
Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID,
|
||||||
Ruleset = { Value = new OsuRuleset().RulesetInfo },
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
enterGameplay();
|
enterGameplay();
|
||||||
|
|
||||||
AddStep("join other user", () => client.AddUser(new APIUser { Id = 1234 }));
|
AddStep("join other user", () => multiplayerClient.AddUser(new APIUser { Id = 1234 }));
|
||||||
AddStep("add item as other user", () => client.AddUserPlaylistItem(1234, new MultiplayerPlaylistItem(new PlaylistItem
|
AddStep("add item as other user", () => multiplayerClient.AddUserPlaylistItem(1234, new MultiplayerPlaylistItem(
|
||||||
{
|
new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
|
||||||
BeatmapID = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo.OnlineID
|
{
|
||||||
})));
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID,
|
||||||
|
})).WaitSafely());
|
||||||
|
|
||||||
AddUntilStep("item arrived in playlist", () => client.Room?.Playlist.Count == 2);
|
AddUntilStep("item arrived in playlist", () => multiplayerClient.Room?.Playlist.Count == 2);
|
||||||
|
|
||||||
AddStep("delete item as other user", () => client.RemoveUserPlaylistItem(1234, 2));
|
AddStep("delete item as other user", () => multiplayerClient.RemoveUserPlaylistItem(1234, 2).WaitSafely());
|
||||||
AddUntilStep("item removed from playlist", () => client.Room?.Playlist.Count == 1);
|
AddUntilStep("item removed from playlist", () => multiplayerClient.Room?.Playlist.Count == 1);
|
||||||
|
|
||||||
AddStep("exit gameplay as initial user", () => multiplayerComponents.MultiplayerScreen.MakeCurrent());
|
AddStep("exit gameplay as initial user", () => multiplayerComponents.MultiplayerScreen.MakeCurrent());
|
||||||
AddUntilStep("queue is empty", () => this.ChildrenOfType<MultiplayerQueueList>().Single().Items.Count == 0);
|
AddUntilStep("queue is empty", () => this.ChildrenOfType<MultiplayerQueueList>().Single().Items.Count == 0);
|
||||||
@ -879,27 +855,26 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
Name = { Value = "Test Room" },
|
Name = { Value = "Test Room" },
|
||||||
Playlist =
|
Playlist =
|
||||||
{
|
{
|
||||||
new PlaylistItem
|
new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
|
||||||
{
|
{
|
||||||
Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
|
||||||
Ruleset = { Value = new OsuRuleset().RulesetInfo },
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
AddStep("join other user and make host", () =>
|
AddStep("join other user and make host", () =>
|
||||||
{
|
{
|
||||||
client.AddUser(new APIUser { Id = 1234 });
|
multiplayerClient.AddUser(new APIUser { Id = 1234 });
|
||||||
client.TransferHost(1234);
|
multiplayerClient.TransferHost(1234);
|
||||||
});
|
});
|
||||||
|
|
||||||
AddStep("set local user spectating", () => client.ChangeUserState(API.LocalUser.Value.OnlineID, MultiplayerUserState.Spectating));
|
AddStep("set local user spectating", () => multiplayerClient.ChangeUserState(API.LocalUser.Value.OnlineID, MultiplayerUserState.Spectating));
|
||||||
AddUntilStep("wait for spectating state", () => client.LocalUser?.State == MultiplayerUserState.Spectating);
|
AddUntilStep("wait for spectating state", () => multiplayerClient.LocalUser?.State == MultiplayerUserState.Spectating);
|
||||||
|
|
||||||
runGameplay();
|
runGameplay();
|
||||||
|
|
||||||
AddStep("exit gameplay for other user", () => client.ChangeUserState(1234, MultiplayerUserState.Idle));
|
AddStep("exit gameplay for other user", () => multiplayerClient.ChangeUserState(1234, MultiplayerUserState.Idle));
|
||||||
AddUntilStep("wait for room to be idle", () => client.Room?.State == MultiplayerRoomState.Open);
|
AddUntilStep("wait for room to be idle", () => multiplayerClient.Room?.State == MultiplayerRoomState.Open);
|
||||||
|
|
||||||
runGameplay();
|
runGameplay();
|
||||||
|
|
||||||
@ -907,13 +882,13 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
{
|
{
|
||||||
AddStep("start match by other user", () =>
|
AddStep("start match by other user", () =>
|
||||||
{
|
{
|
||||||
client.ChangeUserState(1234, MultiplayerUserState.Ready);
|
multiplayerClient.ChangeUserState(1234, MultiplayerUserState.Ready);
|
||||||
client.StartMatch();
|
multiplayerClient.StartMatch();
|
||||||
});
|
});
|
||||||
|
|
||||||
AddUntilStep("wait for loading", () => client.Room?.State == MultiplayerRoomState.WaitingForLoad);
|
AddUntilStep("wait for loading", () => multiplayerClient.Room?.State == MultiplayerRoomState.WaitingForLoad);
|
||||||
AddStep("set player loaded", () => client.ChangeUserState(1234, MultiplayerUserState.Loaded));
|
AddStep("set player loaded", () => multiplayerClient.ChangeUserState(1234, MultiplayerUserState.Loaded));
|
||||||
AddUntilStep("wait for gameplay to start", () => client.Room?.State == MultiplayerRoomState.Playing);
|
AddUntilStep("wait for gameplay to start", () => multiplayerClient.Room?.State == MultiplayerRoomState.Playing);
|
||||||
AddUntilStep("wait for local user to enter spectator", () => multiplayerComponents.CurrentScreen is MultiSpectatorScreen);
|
AddUntilStep("wait for local user to enter spectator", () => multiplayerComponents.CurrentScreen is MultiSpectatorScreen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -938,7 +913,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
|
|
||||||
AddStep("click ready button", () =>
|
AddStep("click ready button", () =>
|
||||||
{
|
{
|
||||||
user = playingUserId == null ? client.LocalUser : client.Room?.Users.Single(u => u.UserID == playingUserId);
|
user = playingUserId == null ? multiplayerClient.LocalUser : multiplayerClient.Room?.Users.Single(u => u.UserID == playingUserId);
|
||||||
lastState = user?.State ?? MultiplayerUserState.Idle;
|
lastState = user?.State ?? MultiplayerUserState.Idle;
|
||||||
|
|
||||||
InputManager.MoveMouseTo(readyButton);
|
InputManager.MoveMouseTo(readyButton);
|
||||||
@ -958,7 +933,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
|
|
||||||
ClickButtonWhenEnabled<MultiplayerMatchSettingsOverlay.CreateOrUpdateButton>();
|
ClickButtonWhenEnabled<MultiplayerMatchSettingsOverlay.CreateOrUpdateButton>();
|
||||||
|
|
||||||
AddUntilStep("wait for join", () => client.RoomJoined);
|
AddUntilStep("wait for join", () => multiplayerClient.RoomJoined);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
{
|
{
|
||||||
base.SetUpSteps();
|
base.SetUpSteps();
|
||||||
|
|
||||||
AddStep("set local user", () => ((DummyAPIAccess)API).LocalUser.Value = LookupCache.GetUserAsync(1).GetResultSafely());
|
AddStep("set local user", () => ((DummyAPIAccess)API).LocalUser.Value = UserLookupCache.GetUserAsync(1).GetResultSafely());
|
||||||
|
|
||||||
AddStep("create leaderboard", () =>
|
AddStep("create leaderboard", () =>
|
||||||
{
|
{
|
||||||
@ -59,7 +59,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
foreach (int user in users)
|
foreach (int user in users)
|
||||||
{
|
{
|
||||||
SpectatorClient.StartPlay(user, Beatmap.Value.BeatmapInfo.OnlineID);
|
SpectatorClient.StartPlay(user, Beatmap.Value.BeatmapInfo.OnlineID);
|
||||||
multiplayerUsers.Add(OnlinePlayDependencies.Client.AddUser(new APIUser { Id = user }, true));
|
multiplayerUsers.Add(OnlinePlayDependencies.MultiplayerClient.AddUser(new APIUser { Id = user }, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
@ -77,7 +77,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
});
|
});
|
||||||
|
|
||||||
AddUntilStep("wait for load", () => leaderboard.IsLoaded);
|
AddUntilStep("wait for load", () => leaderboard.IsLoaded);
|
||||||
AddUntilStep("wait for user population", () => Client.CurrentMatchPlayingUserIds.Count > 0);
|
AddUntilStep("wait for user population", () => MultiplayerClient.CurrentMatchPlayingUserIds.Count > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -91,7 +91,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
public void TestUserQuit()
|
public void TestUserQuit()
|
||||||
{
|
{
|
||||||
foreach (int user in users)
|
foreach (int user in users)
|
||||||
AddStep($"mark user {user} quit", () => Client.RemoveUser(LookupCache.GetUserAsync(user).GetResultSafely().AsNonNull()));
|
AddStep($"mark user {user} quit", () => MultiplayerClient.RemoveUser(UserLookupCache.GetUserAsync(user).GetResultSafely().AsNonNull()));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -48,7 +48,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
{
|
{
|
||||||
base.SetUpSteps();
|
base.SetUpSteps();
|
||||||
|
|
||||||
AddStep("set local user", () => ((DummyAPIAccess)API).LocalUser.Value = LookupCache.GetUserAsync(1).GetResultSafely());
|
AddStep("set local user", () => ((DummyAPIAccess)API).LocalUser.Value = UserLookupCache.GetUserAsync(1).GetResultSafely());
|
||||||
|
|
||||||
AddStep("create leaderboard", () =>
|
AddStep("create leaderboard", () =>
|
||||||
{
|
{
|
||||||
@ -63,7 +63,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
foreach (int user in users)
|
foreach (int user in users)
|
||||||
{
|
{
|
||||||
SpectatorClient.StartPlay(user, Beatmap.Value.BeatmapInfo.OnlineID);
|
SpectatorClient.StartPlay(user, Beatmap.Value.BeatmapInfo.OnlineID);
|
||||||
var roomUser = OnlinePlayDependencies.Client.AddUser(new APIUser { Id = user }, true);
|
var roomUser = OnlinePlayDependencies.MultiplayerClient.AddUser(new APIUser { Id = user }, true);
|
||||||
|
|
||||||
roomUser.MatchState = new TeamVersusUserState
|
roomUser.MatchState = new TeamVersusUserState
|
||||||
{
|
{
|
||||||
@ -105,7 +105,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
});
|
});
|
||||||
|
|
||||||
AddUntilStep("wait for load", () => leaderboard.IsLoaded);
|
AddUntilStep("wait for load", () => leaderboard.IsLoaded);
|
||||||
AddUntilStep("wait for user population", () => Client.CurrentMatchPlayingUserIds.Count > 0);
|
AddUntilStep("wait for user population", () => MultiplayerClient.CurrentMatchPlayingUserIds.Count > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -10,14 +10,18 @@ using osu.Framework.Platform;
|
|||||||
using osu.Framework.Screens;
|
using osu.Framework.Screens;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Online.API;
|
||||||
using osu.Game.Online.API.Requests.Responses;
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
using osu.Game.Online.Multiplayer;
|
using osu.Game.Online.Multiplayer;
|
||||||
using osu.Game.Online.Rooms;
|
using osu.Game.Online.Rooms;
|
||||||
|
using osu.Game.Overlays.Mods;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Rulesets.Osu;
|
using osu.Game.Rulesets.Osu;
|
||||||
|
using osu.Game.Rulesets.Osu.Mods;
|
||||||
using osu.Game.Rulesets.Taiko;
|
using osu.Game.Rulesets.Taiko;
|
||||||
using osu.Game.Rulesets.Taiko.Mods;
|
using osu.Game.Rulesets.Taiko.Mods;
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
|
using osu.Game.Screens.OnlinePlay.Match;
|
||||||
using osu.Game.Screens.OnlinePlay.Multiplayer;
|
using osu.Game.Screens.OnlinePlay.Multiplayer;
|
||||||
using osu.Game.Screens.OnlinePlay.Multiplayer.Match;
|
using osu.Game.Screens.OnlinePlay.Multiplayer.Match;
|
||||||
using osu.Game.Screens.OnlinePlay.Multiplayer.Participants;
|
using osu.Game.Screens.OnlinePlay.Multiplayer.Participants;
|
||||||
@ -69,10 +73,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
{
|
{
|
||||||
AddStep("add playlist item", () =>
|
AddStep("add playlist item", () =>
|
||||||
{
|
{
|
||||||
SelectedRoom.Value.Playlist.Add(new PlaylistItem
|
SelectedRoom.Value.Playlist.Add(new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo)
|
||||||
{
|
{
|
||||||
Beatmap = { Value = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo },
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
|
||||||
Ruleset = { Value = new OsuRuleset().RulesetInfo },
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -86,11 +89,10 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
{
|
{
|
||||||
AddStep("add playlist item", () =>
|
AddStep("add playlist item", () =>
|
||||||
{
|
{
|
||||||
SelectedRoom.Value.Playlist.Add(new PlaylistItem
|
SelectedRoom.Value.Playlist.Add(new PlaylistItem(new TestBeatmap(new TaikoRuleset().RulesetInfo).BeatmapInfo)
|
||||||
{
|
{
|
||||||
Beatmap = { Value = new TestBeatmap(new TaikoRuleset().RulesetInfo).BeatmapInfo },
|
RulesetID = new TaikoRuleset().RulesetInfo.OnlineID,
|
||||||
Ruleset = { Value = new TaikoRuleset().RulesetInfo },
|
AllowedMods = new[] { new APIMod(new TaikoModSwap()) }
|
||||||
AllowedMods = { new TaikoModSwap() }
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -98,7 +100,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
|
|
||||||
AddUntilStep("wait for join", () => RoomJoined);
|
AddUntilStep("wait for join", () => RoomJoined);
|
||||||
|
|
||||||
AddStep("select swap mod", () => Client.ChangeUserMods(API.LocalUser.Value.OnlineID, new[] { new TaikoModSwap() }));
|
AddStep("select swap mod", () => MultiplayerClient.ChangeUserMods(API.LocalUser.Value.OnlineID, new[] { new TaikoModSwap() }));
|
||||||
AddUntilStep("participant panel has mod", () => this.ChildrenOfType<ParticipantPanel>().Any(p => p.ChildrenOfType<ModIcon>().Any(m => m.Mod is TaikoModSwap)));
|
AddUntilStep("participant panel has mod", () => this.ChildrenOfType<ParticipantPanel>().Any(p => p.ChildrenOfType<ModIcon>().Any(m => m.Mod is TaikoModSwap)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,10 +111,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
|
|
||||||
AddStep("set playlist", () =>
|
AddStep("set playlist", () =>
|
||||||
{
|
{
|
||||||
SelectedRoom.Value.Playlist.Add(new PlaylistItem
|
SelectedRoom.Value.Playlist.Add(new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo)
|
||||||
{
|
{
|
||||||
Beatmap = { Value = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo },
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
|
||||||
Ruleset = { Value = new OsuRuleset().RulesetInfo },
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -124,10 +125,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
{
|
{
|
||||||
AddStep("set playlist", () =>
|
AddStep("set playlist", () =>
|
||||||
{
|
{
|
||||||
SelectedRoom.Value.Playlist.Add(new PlaylistItem
|
SelectedRoom.Value.Playlist.Add(new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First()).BeatmapInfo)
|
||||||
{
|
{
|
||||||
Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First()).BeatmapInfo },
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
|
||||||
Ruleset = { Value = new OsuRuleset().RulesetInfo },
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -137,17 +137,39 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
|
|
||||||
AddStep("join other user (ready)", () =>
|
AddStep("join other user (ready)", () =>
|
||||||
{
|
{
|
||||||
Client.AddUser(new APIUser { Id = PLAYER_1_ID });
|
MultiplayerClient.AddUser(new APIUser { Id = PLAYER_1_ID });
|
||||||
Client.ChangeUserState(PLAYER_1_ID, MultiplayerUserState.Ready);
|
MultiplayerClient.ChangeUserState(PLAYER_1_ID, MultiplayerUserState.Ready);
|
||||||
});
|
});
|
||||||
|
|
||||||
ClickButtonWhenEnabled<MultiplayerSpectateButton>();
|
ClickButtonWhenEnabled<MultiplayerSpectateButton>();
|
||||||
|
|
||||||
AddUntilStep("wait for spectating user state", () => Client.LocalUser?.State == MultiplayerUserState.Spectating);
|
AddUntilStep("wait for spectating user state", () => MultiplayerClient.LocalUser?.State == MultiplayerUserState.Spectating);
|
||||||
|
|
||||||
ClickButtonWhenEnabled<MultiplayerReadyButton>();
|
ClickButtonWhenEnabled<MultiplayerReadyButton>();
|
||||||
|
|
||||||
AddUntilStep("match started", () => Client.Room?.State == MultiplayerRoomState.WaitingForLoad);
|
AddUntilStep("match started", () => MultiplayerClient.Room?.State == MultiplayerRoomState.WaitingForLoad);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestFreeModSelectionHasAllowedMods()
|
||||||
|
{
|
||||||
|
AddStep("add playlist item with allowed mod", () =>
|
||||||
|
{
|
||||||
|
SelectedRoom.Value.Playlist.Add(new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo)
|
||||||
|
{
|
||||||
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID,
|
||||||
|
AllowedMods = new[] { new APIMod(new OsuModDoubleTime()) }
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
ClickButtonWhenEnabled<MultiplayerMatchSettingsOverlay.CreateOrUpdateButton>();
|
||||||
|
|
||||||
|
AddUntilStep("wait for join", () => RoomJoined);
|
||||||
|
|
||||||
|
ClickButtonWhenEnabled<RoomSubScreen.UserModSelectButton>();
|
||||||
|
|
||||||
|
AddUntilStep("mod select contains only double time mod",
|
||||||
|
() => this.ChildrenOfType<UserModSelectOverlay>().SingleOrDefault()?.ChildrenOfType<ModButton>().SingleOrDefault()?.Mod is OsuModDoubleTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
{
|
{
|
||||||
AddAssert("one unique panel", () => this.ChildrenOfType<ParticipantPanel>().Select(p => p.User).Distinct().Count() == 1);
|
AddAssert("one unique panel", () => this.ChildrenOfType<ParticipantPanel>().Select(p => p.User).Distinct().Count() == 1);
|
||||||
|
|
||||||
AddStep("add user", () => Client.AddUser(new APIUser
|
AddStep("add user", () => MultiplayerClient.AddUser(new APIUser
|
||||||
{
|
{
|
||||||
Id = 3,
|
Id = 3,
|
||||||
Username = "Second",
|
Username = "Second",
|
||||||
@ -50,15 +50,15 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
{
|
{
|
||||||
AddAssert("one unique panel", () => this.ChildrenOfType<ParticipantPanel>().Select(p => p.User).Distinct().Count() == 1);
|
AddAssert("one unique panel", () => this.ChildrenOfType<ParticipantPanel>().Select(p => p.User).Distinct().Count() == 1);
|
||||||
|
|
||||||
AddStep("add non-resolvable user", () => Client.TestAddUnresolvedUser());
|
AddStep("add non-resolvable user", () => MultiplayerClient.TestAddUnresolvedUser());
|
||||||
AddAssert("null user added", () => Client.Room.AsNonNull().Users.Count(u => u.User == null) == 1);
|
AddAssert("null user added", () => MultiplayerClient.Room.AsNonNull().Users.Count(u => u.User == null) == 1);
|
||||||
|
|
||||||
AddUntilStep("two unique panels", () => this.ChildrenOfType<ParticipantPanel>().Select(p => p.User).Distinct().Count() == 2);
|
AddUntilStep("two unique panels", () => this.ChildrenOfType<ParticipantPanel>().Select(p => p.User).Distinct().Count() == 2);
|
||||||
|
|
||||||
AddStep("kick null user", () => this.ChildrenOfType<ParticipantPanel>().Single(p => p.User.User == null)
|
AddStep("kick null user", () => this.ChildrenOfType<ParticipantPanel>().Single(p => p.User.User == null)
|
||||||
.ChildrenOfType<ParticipantPanel.KickButton>().Single().TriggerClick());
|
.ChildrenOfType<ParticipantPanel.KickButton>().Single().TriggerClick());
|
||||||
|
|
||||||
AddAssert("null user kicked", () => Client.Room.AsNonNull().Users.Count == 1);
|
AddAssert("null user kicked", () => MultiplayerClient.Room.AsNonNull().Users.Count == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -68,7 +68,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
|
|
||||||
AddStep("add a user", () =>
|
AddStep("add a user", () =>
|
||||||
{
|
{
|
||||||
Client.AddUser(secondUser = new APIUser
|
MultiplayerClient.AddUser(secondUser = new APIUser
|
||||||
{
|
{
|
||||||
Id = 3,
|
Id = 3,
|
||||||
Username = "Second",
|
Username = "Second",
|
||||||
@ -76,7 +76,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
AddStep("remove host", () => Client.RemoveUser(API.LocalUser.Value));
|
AddStep("remove host", () => MultiplayerClient.RemoveUser(API.LocalUser.Value));
|
||||||
|
|
||||||
AddAssert("single panel is for second user", () => this.ChildrenOfType<ParticipantPanel>().Single().User.User == secondUser);
|
AddAssert("single panel is for second user", () => this.ChildrenOfType<ParticipantPanel>().Single().User.User == secondUser);
|
||||||
}
|
}
|
||||||
@ -84,21 +84,21 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestGameStateHasPriorityOverDownloadState()
|
public void TestGameStateHasPriorityOverDownloadState()
|
||||||
{
|
{
|
||||||
AddStep("set to downloading map", () => Client.ChangeBeatmapAvailability(BeatmapAvailability.Downloading(0)));
|
AddStep("set to downloading map", () => MultiplayerClient.ChangeBeatmapAvailability(BeatmapAvailability.Downloading(0)));
|
||||||
checkProgressBarVisibility(true);
|
checkProgressBarVisibility(true);
|
||||||
|
|
||||||
AddStep("make user ready", () => Client.ChangeState(MultiplayerUserState.Results));
|
AddStep("make user ready", () => MultiplayerClient.ChangeState(MultiplayerUserState.Results));
|
||||||
checkProgressBarVisibility(false);
|
checkProgressBarVisibility(false);
|
||||||
AddUntilStep("ready mark visible", () => this.ChildrenOfType<StateDisplay>().Single().IsPresent);
|
AddUntilStep("ready mark visible", () => this.ChildrenOfType<StateDisplay>().Single().IsPresent);
|
||||||
|
|
||||||
AddStep("make user ready", () => Client.ChangeState(MultiplayerUserState.Idle));
|
AddStep("make user ready", () => MultiplayerClient.ChangeState(MultiplayerUserState.Idle));
|
||||||
checkProgressBarVisibility(true);
|
checkProgressBarVisibility(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestCorrectInitialState()
|
public void TestCorrectInitialState()
|
||||||
{
|
{
|
||||||
AddStep("set to downloading map", () => Client.ChangeBeatmapAvailability(BeatmapAvailability.Downloading(0)));
|
AddStep("set to downloading map", () => MultiplayerClient.ChangeBeatmapAvailability(BeatmapAvailability.Downloading(0)));
|
||||||
createNewParticipantsList();
|
createNewParticipantsList();
|
||||||
checkProgressBarVisibility(true);
|
checkProgressBarVisibility(true);
|
||||||
}
|
}
|
||||||
@ -106,23 +106,23 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestBeatmapDownloadingStates()
|
public void TestBeatmapDownloadingStates()
|
||||||
{
|
{
|
||||||
AddStep("set to no map", () => Client.ChangeBeatmapAvailability(BeatmapAvailability.NotDownloaded()));
|
AddStep("set to no map", () => MultiplayerClient.ChangeBeatmapAvailability(BeatmapAvailability.NotDownloaded()));
|
||||||
AddStep("set to downloading map", () => Client.ChangeBeatmapAvailability(BeatmapAvailability.Downloading(0)));
|
AddStep("set to downloading map", () => MultiplayerClient.ChangeBeatmapAvailability(BeatmapAvailability.Downloading(0)));
|
||||||
|
|
||||||
checkProgressBarVisibility(true);
|
checkProgressBarVisibility(true);
|
||||||
|
|
||||||
AddRepeatStep("increment progress", () =>
|
AddRepeatStep("increment progress", () =>
|
||||||
{
|
{
|
||||||
float progress = this.ChildrenOfType<ParticipantPanel>().Single().User.BeatmapAvailability.DownloadProgress ?? 0;
|
float progress = this.ChildrenOfType<ParticipantPanel>().Single().User.BeatmapAvailability.DownloadProgress ?? 0;
|
||||||
Client.ChangeBeatmapAvailability(BeatmapAvailability.Downloading(progress + RNG.NextSingle(0.1f)));
|
MultiplayerClient.ChangeBeatmapAvailability(BeatmapAvailability.Downloading(progress + RNG.NextSingle(0.1f)));
|
||||||
}, 25);
|
}, 25);
|
||||||
|
|
||||||
AddAssert("progress bar increased", () => this.ChildrenOfType<ProgressBar>().Single().Current.Value > 0);
|
AddAssert("progress bar increased", () => this.ChildrenOfType<ProgressBar>().Single().Current.Value > 0);
|
||||||
|
|
||||||
AddStep("set to importing map", () => Client.ChangeBeatmapAvailability(BeatmapAvailability.Importing()));
|
AddStep("set to importing map", () => MultiplayerClient.ChangeBeatmapAvailability(BeatmapAvailability.Importing()));
|
||||||
checkProgressBarVisibility(false);
|
checkProgressBarVisibility(false);
|
||||||
|
|
||||||
AddStep("set to available", () => Client.ChangeBeatmapAvailability(BeatmapAvailability.LocallyAvailable()));
|
AddStep("set to available", () => MultiplayerClient.ChangeBeatmapAvailability(BeatmapAvailability.LocallyAvailable()));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -130,24 +130,24 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
{
|
{
|
||||||
AddAssert("ready mark invisible", () => !this.ChildrenOfType<StateDisplay>().Single().IsPresent);
|
AddAssert("ready mark invisible", () => !this.ChildrenOfType<StateDisplay>().Single().IsPresent);
|
||||||
|
|
||||||
AddStep("make user ready", () => Client.ChangeState(MultiplayerUserState.Ready));
|
AddStep("make user ready", () => MultiplayerClient.ChangeState(MultiplayerUserState.Ready));
|
||||||
AddUntilStep("ready mark visible", () => this.ChildrenOfType<StateDisplay>().Single().IsPresent);
|
AddUntilStep("ready mark visible", () => this.ChildrenOfType<StateDisplay>().Single().IsPresent);
|
||||||
|
|
||||||
AddStep("make user idle", () => Client.ChangeState(MultiplayerUserState.Idle));
|
AddStep("make user idle", () => MultiplayerClient.ChangeState(MultiplayerUserState.Idle));
|
||||||
AddUntilStep("ready mark invisible", () => !this.ChildrenOfType<StateDisplay>().Single().IsPresent);
|
AddUntilStep("ready mark invisible", () => !this.ChildrenOfType<StateDisplay>().Single().IsPresent);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestToggleSpectateState()
|
public void TestToggleSpectateState()
|
||||||
{
|
{
|
||||||
AddStep("make user spectating", () => Client.ChangeState(MultiplayerUserState.Spectating));
|
AddStep("make user spectating", () => MultiplayerClient.ChangeState(MultiplayerUserState.Spectating));
|
||||||
AddStep("make user idle", () => Client.ChangeState(MultiplayerUserState.Idle));
|
AddStep("make user idle", () => MultiplayerClient.ChangeState(MultiplayerUserState.Idle));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestCrownChangesStateWhenHostTransferred()
|
public void TestCrownChangesStateWhenHostTransferred()
|
||||||
{
|
{
|
||||||
AddStep("add user", () => Client.AddUser(new APIUser
|
AddStep("add user", () => MultiplayerClient.AddUser(new APIUser
|
||||||
{
|
{
|
||||||
Id = 3,
|
Id = 3,
|
||||||
Username = "Second",
|
Username = "Second",
|
||||||
@ -157,7 +157,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
AddUntilStep("first user crown visible", () => this.ChildrenOfType<ParticipantPanel>().ElementAt(0).ChildrenOfType<SpriteIcon>().First().Alpha == 1);
|
AddUntilStep("first user crown visible", () => this.ChildrenOfType<ParticipantPanel>().ElementAt(0).ChildrenOfType<SpriteIcon>().First().Alpha == 1);
|
||||||
AddUntilStep("second user crown hidden", () => this.ChildrenOfType<ParticipantPanel>().ElementAt(1).ChildrenOfType<SpriteIcon>().First().Alpha == 0);
|
AddUntilStep("second user crown hidden", () => this.ChildrenOfType<ParticipantPanel>().ElementAt(1).ChildrenOfType<SpriteIcon>().First().Alpha == 0);
|
||||||
|
|
||||||
AddStep("make second user host", () => Client.TransferHost(3));
|
AddStep("make second user host", () => MultiplayerClient.TransferHost(3));
|
||||||
|
|
||||||
AddUntilStep("first user crown hidden", () => this.ChildrenOfType<ParticipantPanel>().ElementAt(0).ChildrenOfType<SpriteIcon>().First().Alpha == 0);
|
AddUntilStep("first user crown hidden", () => this.ChildrenOfType<ParticipantPanel>().ElementAt(0).ChildrenOfType<SpriteIcon>().First().Alpha == 0);
|
||||||
AddUntilStep("second user crown visible", () => this.ChildrenOfType<ParticipantPanel>().ElementAt(1).ChildrenOfType<SpriteIcon>().First().Alpha == 1);
|
AddUntilStep("second user crown visible", () => this.ChildrenOfType<ParticipantPanel>().ElementAt(1).ChildrenOfType<SpriteIcon>().First().Alpha == 1);
|
||||||
@ -166,7 +166,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestKickButtonOnlyPresentWhenHost()
|
public void TestKickButtonOnlyPresentWhenHost()
|
||||||
{
|
{
|
||||||
AddStep("add user", () => Client.AddUser(new APIUser
|
AddStep("add user", () => MultiplayerClient.AddUser(new APIUser
|
||||||
{
|
{
|
||||||
Id = 3,
|
Id = 3,
|
||||||
Username = "Second",
|
Username = "Second",
|
||||||
@ -175,11 +175,11 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
|
|
||||||
AddUntilStep("kick buttons visible", () => this.ChildrenOfType<ParticipantPanel.KickButton>().Count(d => d.IsPresent) == 1);
|
AddUntilStep("kick buttons visible", () => this.ChildrenOfType<ParticipantPanel.KickButton>().Count(d => d.IsPresent) == 1);
|
||||||
|
|
||||||
AddStep("make second user host", () => Client.TransferHost(3));
|
AddStep("make second user host", () => MultiplayerClient.TransferHost(3));
|
||||||
|
|
||||||
AddUntilStep("kick buttons not visible", () => this.ChildrenOfType<ParticipantPanel.KickButton>().Count(d => d.IsPresent) == 0);
|
AddUntilStep("kick buttons not visible", () => this.ChildrenOfType<ParticipantPanel.KickButton>().Count(d => d.IsPresent) == 0);
|
||||||
|
|
||||||
AddStep("make local user host again", () => Client.TransferHost(API.LocalUser.Value.Id));
|
AddStep("make local user host again", () => MultiplayerClient.TransferHost(API.LocalUser.Value.Id));
|
||||||
|
|
||||||
AddUntilStep("kick buttons visible", () => this.ChildrenOfType<ParticipantPanel.KickButton>().Count(d => d.IsPresent) == 1);
|
AddUntilStep("kick buttons visible", () => this.ChildrenOfType<ParticipantPanel.KickButton>().Count(d => d.IsPresent) == 1);
|
||||||
}
|
}
|
||||||
@ -187,7 +187,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestKickButtonKicks()
|
public void TestKickButtonKicks()
|
||||||
{
|
{
|
||||||
AddStep("add user", () => Client.AddUser(new APIUser
|
AddStep("add user", () => MultiplayerClient.AddUser(new APIUser
|
||||||
{
|
{
|
||||||
Id = 3,
|
Id = 3,
|
||||||
Username = "Second",
|
Username = "Second",
|
||||||
@ -196,7 +196,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
|
|
||||||
AddStep("kick second user", () => this.ChildrenOfType<ParticipantPanel.KickButton>().Single(d => d.IsPresent).TriggerClick());
|
AddStep("kick second user", () => this.ChildrenOfType<ParticipantPanel.KickButton>().Single(d => d.IsPresent).TriggerClick());
|
||||||
|
|
||||||
AddAssert("second user kicked", () => Client.Room?.Users.Single().UserID == API.LocalUser.Value.Id);
|
AddAssert("second user kicked", () => MultiplayerClient.Room?.Users.Single().UserID == API.LocalUser.Value.Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -206,7 +206,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
{
|
{
|
||||||
for (int i = 0; i < 20; i++)
|
for (int i = 0; i < 20; i++)
|
||||||
{
|
{
|
||||||
Client.AddUser(new APIUser
|
MultiplayerClient.AddUser(new APIUser
|
||||||
{
|
{
|
||||||
Id = i,
|
Id = i,
|
||||||
Username = $"User {i}",
|
Username = $"User {i}",
|
||||||
@ -220,7 +220,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg",
|
CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg",
|
||||||
});
|
});
|
||||||
|
|
||||||
Client.ChangeUserState(i, (MultiplayerUserState)RNG.Next(0, (int)MultiplayerUserState.Results + 1));
|
MultiplayerClient.ChangeUserState(i, (MultiplayerUserState)RNG.Next(0, (int)MultiplayerUserState.Results + 1));
|
||||||
|
|
||||||
if (RNG.NextBool())
|
if (RNG.NextBool())
|
||||||
{
|
{
|
||||||
@ -229,15 +229,15 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
switch (beatmapState)
|
switch (beatmapState)
|
||||||
{
|
{
|
||||||
case DownloadState.NotDownloaded:
|
case DownloadState.NotDownloaded:
|
||||||
Client.ChangeUserBeatmapAvailability(i, BeatmapAvailability.NotDownloaded());
|
MultiplayerClient.ChangeUserBeatmapAvailability(i, BeatmapAvailability.NotDownloaded());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DownloadState.Downloading:
|
case DownloadState.Downloading:
|
||||||
Client.ChangeUserBeatmapAvailability(i, BeatmapAvailability.Downloading(RNG.NextSingle()));
|
MultiplayerClient.ChangeUserBeatmapAvailability(i, BeatmapAvailability.Downloading(RNG.NextSingle()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DownloadState.Importing:
|
case DownloadState.Importing:
|
||||||
Client.ChangeUserBeatmapAvailability(i, BeatmapAvailability.Importing());
|
MultiplayerClient.ChangeUserBeatmapAvailability(i, BeatmapAvailability.Importing());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -250,7 +250,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
{
|
{
|
||||||
AddStep("add user", () =>
|
AddStep("add user", () =>
|
||||||
{
|
{
|
||||||
Client.AddUser(new APIUser
|
MultiplayerClient.AddUser(new APIUser
|
||||||
{
|
{
|
||||||
Id = 0,
|
Id = 0,
|
||||||
Username = "User 0",
|
Username = "User 0",
|
||||||
@ -264,7 +264,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg",
|
CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg",
|
||||||
});
|
});
|
||||||
|
|
||||||
Client.ChangeUserMods(0, new Mod[]
|
MultiplayerClient.ChangeUserMods(0, new Mod[]
|
||||||
{
|
{
|
||||||
new OsuModHardRock(),
|
new OsuModHardRock(),
|
||||||
new OsuModDifficultyAdjust { ApproachRate = { Value = 1 } }
|
new OsuModDifficultyAdjust { ApproachRate = { Value = 1 } }
|
||||||
@ -274,12 +274,12 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
for (var i = MultiplayerUserState.Idle; i < MultiplayerUserState.Results; i++)
|
for (var i = MultiplayerUserState.Idle; i < MultiplayerUserState.Results; i++)
|
||||||
{
|
{
|
||||||
var state = i;
|
var state = i;
|
||||||
AddStep($"set state: {state}", () => Client.ChangeUserState(0, state));
|
AddStep($"set state: {state}", () => MultiplayerClient.ChangeUserState(0, state));
|
||||||
}
|
}
|
||||||
|
|
||||||
AddStep("set state: downloading", () => Client.ChangeUserBeatmapAvailability(0, BeatmapAvailability.Downloading(0)));
|
AddStep("set state: downloading", () => MultiplayerClient.ChangeUserBeatmapAvailability(0, BeatmapAvailability.Downloading(0)));
|
||||||
|
|
||||||
AddStep("set state: locally available", () => Client.ChangeUserBeatmapAvailability(0, BeatmapAvailability.LocallyAvailable()));
|
AddStep("set state: locally available", () => MultiplayerClient.ChangeUserBeatmapAvailability(0, BeatmapAvailability.LocallyAvailable()));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -287,7 +287,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
{
|
{
|
||||||
AddStep("add dummy mods", () =>
|
AddStep("add dummy mods", () =>
|
||||||
{
|
{
|
||||||
Client.ChangeUserMods(new Mod[]
|
MultiplayerClient.ChangeUserMods(new Mod[]
|
||||||
{
|
{
|
||||||
new OsuModNoFail(),
|
new OsuModNoFail(),
|
||||||
new OsuModDoubleTime()
|
new OsuModDoubleTime()
|
||||||
@ -296,7 +296,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
|
|
||||||
AddStep("add user with mods", () =>
|
AddStep("add user with mods", () =>
|
||||||
{
|
{
|
||||||
Client.AddUser(new APIUser
|
MultiplayerClient.AddUser(new APIUser
|
||||||
{
|
{
|
||||||
Id = 0,
|
Id = 0,
|
||||||
Username = "Baka",
|
Username = "Baka",
|
||||||
@ -309,34 +309,34 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
},
|
},
|
||||||
CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg",
|
CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg",
|
||||||
});
|
});
|
||||||
Client.ChangeUserMods(0, new Mod[]
|
MultiplayerClient.ChangeUserMods(0, new Mod[]
|
||||||
{
|
{
|
||||||
new OsuModHardRock(),
|
new OsuModHardRock(),
|
||||||
new OsuModDoubleTime()
|
new OsuModDoubleTime()
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
AddStep("set 0 ready", () => Client.ChangeState(MultiplayerUserState.Ready));
|
AddStep("set 0 ready", () => MultiplayerClient.ChangeState(MultiplayerUserState.Ready));
|
||||||
|
|
||||||
AddStep("set 1 spectate", () => Client.ChangeUserState(0, MultiplayerUserState.Spectating));
|
AddStep("set 1 spectate", () => MultiplayerClient.ChangeUserState(0, MultiplayerUserState.Spectating));
|
||||||
|
|
||||||
// Have to set back to idle due to status priority.
|
// Have to set back to idle due to status priority.
|
||||||
AddStep("set 0 no map, 1 ready", () =>
|
AddStep("set 0 no map, 1 ready", () =>
|
||||||
{
|
{
|
||||||
Client.ChangeState(MultiplayerUserState.Idle);
|
MultiplayerClient.ChangeState(MultiplayerUserState.Idle);
|
||||||
Client.ChangeBeatmapAvailability(BeatmapAvailability.NotDownloaded());
|
MultiplayerClient.ChangeBeatmapAvailability(BeatmapAvailability.NotDownloaded());
|
||||||
Client.ChangeUserState(0, MultiplayerUserState.Ready);
|
MultiplayerClient.ChangeUserState(0, MultiplayerUserState.Ready);
|
||||||
});
|
});
|
||||||
|
|
||||||
AddStep("set 0 downloading", () => Client.ChangeBeatmapAvailability(BeatmapAvailability.Downloading(0)));
|
AddStep("set 0 downloading", () => MultiplayerClient.ChangeBeatmapAvailability(BeatmapAvailability.Downloading(0)));
|
||||||
|
|
||||||
AddStep("set 0 spectate", () => Client.ChangeUserState(0, MultiplayerUserState.Spectating));
|
AddStep("set 0 spectate", () => MultiplayerClient.ChangeUserState(0, MultiplayerUserState.Spectating));
|
||||||
|
|
||||||
AddStep("make both default", () =>
|
AddStep("make both default", () =>
|
||||||
{
|
{
|
||||||
Client.ChangeBeatmapAvailability(BeatmapAvailability.LocallyAvailable());
|
MultiplayerClient.ChangeBeatmapAvailability(BeatmapAvailability.LocallyAvailable());
|
||||||
Client.ChangeUserState(0, MultiplayerUserState.Idle);
|
MultiplayerClient.ChangeUserState(0, MultiplayerUserState.Idle);
|
||||||
Client.ChangeState(MultiplayerUserState.Idle);
|
MultiplayerClient.ChangeState(MultiplayerUserState.Idle);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,15 +28,14 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
|
|
||||||
AddStep("initialise gameplay", () =>
|
AddStep("initialise gameplay", () =>
|
||||||
{
|
{
|
||||||
Stack.Push(player = new MultiplayerPlayer(Client.APIRoom, new PlaylistItem
|
Stack.Push(player = new MultiplayerPlayer(MultiplayerClient.APIRoom, new PlaylistItem(Beatmap.Value.BeatmapInfo)
|
||||||
{
|
{
|
||||||
Beatmap = { Value = Beatmap.Value.BeatmapInfo },
|
RulesetID = Beatmap.Value.BeatmapInfo.Ruleset.OnlineID,
|
||||||
Ruleset = { Value = Beatmap.Value.BeatmapInfo.Ruleset }
|
}, MultiplayerClient.Room?.Users.ToArray()));
|
||||||
}, Client.Room?.Users.ToArray()));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
AddUntilStep("wait for player to be current", () => player.IsCurrentScreen() && player.IsLoaded);
|
AddUntilStep("wait for player to be current", () => player.IsCurrentScreen() && player.IsLoaded);
|
||||||
AddStep("start gameplay", () => ((IMultiplayerClient)Client).MatchStarted());
|
AddStep("start gameplay", () => ((IMultiplayerClient)MultiplayerClient).MatchStarted());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -60,7 +60,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
importedBeatmap = importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0);
|
importedBeatmap = importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
AddStep("change to all players mode", () => Client.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers }));
|
AddStep("change to all players mode", () => MultiplayerClient.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers }).WaitSafely());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -97,19 +97,19 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
addItemStep();
|
addItemStep();
|
||||||
addItemStep();
|
addItemStep();
|
||||||
|
|
||||||
AddStep("finish current item", () => Client.FinishCurrentItem());
|
AddStep("finish current item", () => MultiplayerClient.FinishCurrentItem().WaitSafely());
|
||||||
|
|
||||||
assertItemInHistoryListStep(1, 0);
|
assertItemInHistoryListStep(1, 0);
|
||||||
assertItemInQueueListStep(2, 0);
|
assertItemInQueueListStep(2, 0);
|
||||||
assertItemInQueueListStep(3, 1);
|
assertItemInQueueListStep(3, 1);
|
||||||
|
|
||||||
AddStep("finish current item", () => Client.FinishCurrentItem());
|
AddStep("finish current item", () => MultiplayerClient.FinishCurrentItem().WaitSafely());
|
||||||
|
|
||||||
assertItemInHistoryListStep(2, 0);
|
assertItemInHistoryListStep(2, 0);
|
||||||
assertItemInHistoryListStep(1, 1);
|
assertItemInHistoryListStep(1, 1);
|
||||||
assertItemInQueueListStep(3, 0);
|
assertItemInQueueListStep(3, 0);
|
||||||
|
|
||||||
AddStep("finish current item", () => Client.FinishCurrentItem());
|
AddStep("finish current item", () => MultiplayerClient.FinishCurrentItem().WaitSafely());
|
||||||
|
|
||||||
assertItemInHistoryListStep(3, 0);
|
assertItemInHistoryListStep(3, 0);
|
||||||
assertItemInHistoryListStep(2, 1);
|
assertItemInHistoryListStep(2, 1);
|
||||||
@ -120,7 +120,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
public void TestListsClearedWhenRoomLeft()
|
public void TestListsClearedWhenRoomLeft()
|
||||||
{
|
{
|
||||||
addItemStep();
|
addItemStep();
|
||||||
AddStep("finish current item", () => Client.FinishCurrentItem());
|
AddStep("finish current item", () => MultiplayerClient.FinishCurrentItem().WaitSafely());
|
||||||
|
|
||||||
AddStep("leave room", () => RoomManager.PartRoom());
|
AddStep("leave room", () => RoomManager.PartRoom());
|
||||||
AddUntilStep("wait for room part", () => !RoomJoined);
|
AddUntilStep("wait for room part", () => !RoomJoined);
|
||||||
@ -143,15 +143,13 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
Name = { Value = "test name" },
|
Name = { Value = "test name" },
|
||||||
Playlist =
|
Playlist =
|
||||||
{
|
{
|
||||||
new PlaylistItem
|
new PlaylistItem(new TestBeatmap(Ruleset.Value).BeatmapInfo)
|
||||||
{
|
{
|
||||||
Beatmap = { Value = new TestBeatmap(Ruleset.Value).BeatmapInfo },
|
RulesetID = Ruleset.Value.OnlineID
|
||||||
Ruleset = { Value = Ruleset.Value }
|
|
||||||
},
|
},
|
||||||
new PlaylistItem
|
new PlaylistItem(new TestBeatmap(Ruleset.Value).BeatmapInfo)
|
||||||
{
|
{
|
||||||
Beatmap = { Value = new TestBeatmap(Ruleset.Value).BeatmapInfo },
|
RulesetID = Ruleset.Value.OnlineID,
|
||||||
Ruleset = { Value = Ruleset.Value },
|
|
||||||
Expired = true
|
Expired = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -167,10 +165,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds a step to create a new playlist item.
|
/// Adds a step to create a new playlist item.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void addItemStep(bool expired = false) => AddStep("add item", () => Client.AddPlaylistItem(new MultiplayerPlaylistItem(new PlaylistItem
|
private void addItemStep(bool expired = false) => AddStep("add item", () => MultiplayerClient.AddPlaylistItem(new MultiplayerPlaylistItem(new PlaylistItem(importedBeatmap)
|
||||||
{
|
{
|
||||||
Beatmap = { Value = importedBeatmap },
|
|
||||||
BeatmapID = importedBeatmap.OnlineID,
|
|
||||||
Expired = expired,
|
Expired = expired,
|
||||||
PlayedAt = DateTimeOffset.Now
|
PlayedAt = DateTimeOffset.Now
|
||||||
})));
|
})));
|
||||||
|
@ -12,7 +12,6 @@ using osu.Framework.Graphics.Containers;
|
|||||||
using osu.Framework.Platform;
|
using osu.Framework.Platform;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Database;
|
|
||||||
using osu.Game.Online.API.Requests.Responses;
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
using osu.Game.Online.Multiplayer;
|
using osu.Game.Online.Multiplayer;
|
||||||
using osu.Game.Online.Rooms;
|
using osu.Game.Online.Rooms;
|
||||||
@ -26,9 +25,6 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
{
|
{
|
||||||
public class TestSceneMultiplayerQueueList : MultiplayerTestScene
|
public class TestSceneMultiplayerQueueList : MultiplayerTestScene
|
||||||
{
|
{
|
||||||
[Cached(typeof(UserLookupCache))]
|
|
||||||
private readonly TestUserLookupCache userLookupCache = new TestUserLookupCache();
|
|
||||||
|
|
||||||
private MultiplayerQueueList playlist;
|
private MultiplayerQueueList playlist;
|
||||||
private BeatmapManager beatmaps;
|
private BeatmapManager beatmaps;
|
||||||
private RulesetStore rulesets;
|
private RulesetStore rulesets;
|
||||||
@ -54,7 +50,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
Size = new Vector2(500, 300),
|
Size = new Vector2(500, 300),
|
||||||
Items = { BindTarget = Client.APIRoom!.Playlist }
|
Items = { BindTarget = MultiplayerClient.APIRoom!.Playlist }
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -65,14 +61,14 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
importedBeatmap = importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0);
|
importedBeatmap = importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
AddStep("change to all players mode", () => Client.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers }));
|
AddStep("change to all players mode", () => MultiplayerClient.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers }).WaitSafely());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestDeleteButtonAlwaysVisibleForHost()
|
public void TestDeleteButtonAlwaysVisibleForHost()
|
||||||
{
|
{
|
||||||
AddStep("set all players queue mode", () => Client.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers }));
|
AddStep("set all players queue mode", () => MultiplayerClient.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers }).WaitSafely());
|
||||||
AddUntilStep("wait for queue mode change", () => Client.APIRoom?.QueueMode.Value == QueueMode.AllPlayers);
|
AddUntilStep("wait for queue mode change", () => MultiplayerClient.APIRoom?.QueueMode.Value == QueueMode.AllPlayers);
|
||||||
|
|
||||||
addPlaylistItem(() => API.LocalUser.Value.OnlineID);
|
addPlaylistItem(() => API.LocalUser.Value.OnlineID);
|
||||||
assertDeleteButtonVisibility(1, true);
|
assertDeleteButtonVisibility(1, true);
|
||||||
@ -83,18 +79,18 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestDeleteButtonOnlyVisibleForItemOwnerIfNotHost()
|
public void TestDeleteButtonOnlyVisibleForItemOwnerIfNotHost()
|
||||||
{
|
{
|
||||||
AddStep("set all players queue mode", () => Client.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers }));
|
AddStep("set all players queue mode", () => MultiplayerClient.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers }).WaitSafely());
|
||||||
AddUntilStep("wait for queue mode change", () => Client.APIRoom?.QueueMode.Value == QueueMode.AllPlayers);
|
AddUntilStep("wait for queue mode change", () => MultiplayerClient.APIRoom?.QueueMode.Value == QueueMode.AllPlayers);
|
||||||
|
|
||||||
AddStep("join other user", () => Client.AddUser(new APIUser { Id = 1234 }));
|
AddStep("join other user", () => MultiplayerClient.AddUser(new APIUser { Id = 1234 }));
|
||||||
AddStep("set other user as host", () => Client.TransferHost(1234));
|
AddStep("set other user as host", () => MultiplayerClient.TransferHost(1234));
|
||||||
|
|
||||||
addPlaylistItem(() => API.LocalUser.Value.OnlineID);
|
addPlaylistItem(() => API.LocalUser.Value.OnlineID);
|
||||||
assertDeleteButtonVisibility(1, true);
|
assertDeleteButtonVisibility(1, true);
|
||||||
addPlaylistItem(() => 1234);
|
addPlaylistItem(() => 1234);
|
||||||
assertDeleteButtonVisibility(2, false);
|
assertDeleteButtonVisibility(2, false);
|
||||||
|
|
||||||
AddStep("set local user as host", () => Client.TransferHost(API.LocalUser.Value.OnlineID));
|
AddStep("set local user as host", () => MultiplayerClient.TransferHost(API.LocalUser.Value.OnlineID));
|
||||||
assertDeleteButtonVisibility(1, true);
|
assertDeleteButtonVisibility(1, true);
|
||||||
assertDeleteButtonVisibility(2, true);
|
assertDeleteButtonVisibility(2, true);
|
||||||
}
|
}
|
||||||
@ -102,16 +98,16 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestCurrentItemDoesNotHaveDeleteButton()
|
public void TestCurrentItemDoesNotHaveDeleteButton()
|
||||||
{
|
{
|
||||||
AddStep("set all players queue mode", () => Client.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers }));
|
AddStep("set all players queue mode", () => MultiplayerClient.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers }).WaitSafely());
|
||||||
AddUntilStep("wait for queue mode change", () => Client.APIRoom?.QueueMode.Value == QueueMode.AllPlayers);
|
AddUntilStep("wait for queue mode change", () => MultiplayerClient.APIRoom?.QueueMode.Value == QueueMode.AllPlayers);
|
||||||
|
|
||||||
addPlaylistItem(() => API.LocalUser.Value.OnlineID);
|
addPlaylistItem(() => API.LocalUser.Value.OnlineID);
|
||||||
|
|
||||||
assertDeleteButtonVisibility(0, false);
|
assertDeleteButtonVisibility(0, false);
|
||||||
assertDeleteButtonVisibility(1, true);
|
assertDeleteButtonVisibility(1, true);
|
||||||
|
|
||||||
AddStep("finish current item", () => Client.FinishCurrentItem());
|
AddStep("finish current item", () => MultiplayerClient.FinishCurrentItem().WaitSafely());
|
||||||
AddUntilStep("wait for next item to be selected", () => Client.Room?.Settings.PlaylistItemId == 2);
|
AddUntilStep("wait for next item to be selected", () => MultiplayerClient.Room?.Settings.PlaylistItemId == 2);
|
||||||
AddUntilStep("wait for two items in playlist", () => playlist.ChildrenOfType<DrawableRoomPlaylistItem>().Count() == 2);
|
AddUntilStep("wait for two items in playlist", () => playlist.ChildrenOfType<DrawableRoomPlaylistItem>().Count() == 2);
|
||||||
|
|
||||||
assertDeleteButtonVisibility(0, false);
|
assertDeleteButtonVisibility(0, false);
|
||||||
@ -124,13 +120,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
|
|
||||||
AddStep("add playlist item", () =>
|
AddStep("add playlist item", () =>
|
||||||
{
|
{
|
||||||
MultiplayerPlaylistItem item = new MultiplayerPlaylistItem(new PlaylistItem
|
MultiplayerPlaylistItem item = new MultiplayerPlaylistItem(new PlaylistItem(importedBeatmap));
|
||||||
{
|
|
||||||
Beatmap = { Value = importedBeatmap },
|
|
||||||
BeatmapID = importedBeatmap.OnlineID,
|
|
||||||
});
|
|
||||||
|
|
||||||
Client.AddUserPlaylistItem(userId(), item);
|
MultiplayerClient.AddUserPlaylistItem(userId(), item).WaitSafely();
|
||||||
|
|
||||||
itemId = item.ID;
|
itemId = item.ID;
|
||||||
});
|
});
|
||||||
|
@ -54,10 +54,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
|
|
||||||
importedSet = beatmaps.GetAllUsableBeatmapSets().First();
|
importedSet = beatmaps.GetAllUsableBeatmapSets().First();
|
||||||
Beatmap.Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First());
|
Beatmap.Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First());
|
||||||
selectedItem.Value = new PlaylistItem
|
selectedItem.Value = new PlaylistItem(Beatmap.Value.BeatmapInfo)
|
||||||
{
|
{
|
||||||
Beatmap = { Value = Beatmap.Value.BeatmapInfo },
|
RulesetID = Beatmap.Value.BeatmapInfo.Ruleset.OnlineID
|
||||||
Ruleset = { Value = Beatmap.Value.BeatmapInfo.Ruleset },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (button != null)
|
if (button != null)
|
||||||
@ -74,13 +73,13 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
|
|
||||||
Task.Run(async () =>
|
Task.Run(async () =>
|
||||||
{
|
{
|
||||||
if (Client.IsHost && Client.LocalUser?.State == MultiplayerUserState.Ready)
|
if (MultiplayerClient.IsHost && MultiplayerClient.LocalUser?.State == MultiplayerUserState.Ready)
|
||||||
{
|
{
|
||||||
await Client.StartMatch();
|
await MultiplayerClient.StartMatch();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await Client.ToggleReady();
|
await MultiplayerClient.ToggleReady();
|
||||||
|
|
||||||
readyClickOperation.Dispose();
|
readyClickOperation.Dispose();
|
||||||
});
|
});
|
||||||
@ -110,15 +109,15 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
{
|
{
|
||||||
AddStep("add second user as host", () =>
|
AddStep("add second user as host", () =>
|
||||||
{
|
{
|
||||||
Client.AddUser(new APIUser { Id = 2, Username = "Another user" });
|
MultiplayerClient.AddUser(new APIUser { Id = 2, Username = "Another user" });
|
||||||
Client.TransferHost(2);
|
MultiplayerClient.TransferHost(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
ClickButtonWhenEnabled<MultiplayerReadyButton>();
|
ClickButtonWhenEnabled<MultiplayerReadyButton>();
|
||||||
AddUntilStep("user is ready", () => Client.Room?.Users[0].State == MultiplayerUserState.Ready);
|
AddUntilStep("user is ready", () => MultiplayerClient.Room?.Users[0].State == MultiplayerUserState.Ready);
|
||||||
|
|
||||||
ClickButtonWhenEnabled<MultiplayerReadyButton>();
|
ClickButtonWhenEnabled<MultiplayerReadyButton>();
|
||||||
AddUntilStep("user is idle", () => Client.Room?.Users[0].State == MultiplayerUserState.Idle);
|
AddUntilStep("user is idle", () => MultiplayerClient.Room?.Users[0].State == MultiplayerUserState.Idle);
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase(true)]
|
[TestCase(true)]
|
||||||
@ -127,14 +126,14 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
{
|
{
|
||||||
AddStep("setup", () =>
|
AddStep("setup", () =>
|
||||||
{
|
{
|
||||||
Client.TransferHost(Client.Room?.Users[0].UserID ?? 0);
|
MultiplayerClient.TransferHost(MultiplayerClient.Room?.Users[0].UserID ?? 0);
|
||||||
|
|
||||||
if (!allReady)
|
if (!allReady)
|
||||||
Client.AddUser(new APIUser { Id = 2, Username = "Another user" });
|
MultiplayerClient.AddUser(new APIUser { Id = 2, Username = "Another user" });
|
||||||
});
|
});
|
||||||
|
|
||||||
ClickButtonWhenEnabled<MultiplayerReadyButton>();
|
ClickButtonWhenEnabled<MultiplayerReadyButton>();
|
||||||
AddUntilStep("user is ready", () => Client.Room?.Users[0].State == MultiplayerUserState.Ready);
|
AddUntilStep("user is ready", () => MultiplayerClient.Room?.Users[0].State == MultiplayerUserState.Ready);
|
||||||
|
|
||||||
verifyGameplayStartFlow();
|
verifyGameplayStartFlow();
|
||||||
}
|
}
|
||||||
@ -144,12 +143,12 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
{
|
{
|
||||||
AddStep("add host", () =>
|
AddStep("add host", () =>
|
||||||
{
|
{
|
||||||
Client.AddUser(new APIUser { Id = 2, Username = "Another user" });
|
MultiplayerClient.AddUser(new APIUser { Id = 2, Username = "Another user" });
|
||||||
Client.TransferHost(2);
|
MultiplayerClient.TransferHost(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
ClickButtonWhenEnabled<MultiplayerReadyButton>();
|
ClickButtonWhenEnabled<MultiplayerReadyButton>();
|
||||||
AddStep("make user host", () => Client.TransferHost(Client.Room?.Users[0].UserID ?? 0));
|
AddStep("make user host", () => MultiplayerClient.TransferHost(MultiplayerClient.Room?.Users[0].UserID ?? 0));
|
||||||
|
|
||||||
verifyGameplayStartFlow();
|
verifyGameplayStartFlow();
|
||||||
}
|
}
|
||||||
@ -159,17 +158,17 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
{
|
{
|
||||||
AddStep("setup", () =>
|
AddStep("setup", () =>
|
||||||
{
|
{
|
||||||
Client.TransferHost(Client.Room?.Users[0].UserID ?? 0);
|
MultiplayerClient.TransferHost(MultiplayerClient.Room?.Users[0].UserID ?? 0);
|
||||||
Client.AddUser(new APIUser { Id = 2, Username = "Another user" });
|
MultiplayerClient.AddUser(new APIUser { Id = 2, Username = "Another user" });
|
||||||
});
|
});
|
||||||
|
|
||||||
ClickButtonWhenEnabled<MultiplayerReadyButton>();
|
ClickButtonWhenEnabled<MultiplayerReadyButton>();
|
||||||
AddUntilStep("user is ready", () => Client.Room?.Users[0].State == MultiplayerUserState.Ready);
|
AddUntilStep("user is ready", () => MultiplayerClient.Room?.Users[0].State == MultiplayerUserState.Ready);
|
||||||
|
|
||||||
AddStep("transfer host", () => Client.TransferHost(Client.Room?.Users[1].UserID ?? 0));
|
AddStep("transfer host", () => MultiplayerClient.TransferHost(MultiplayerClient.Room?.Users[1].UserID ?? 0));
|
||||||
|
|
||||||
ClickButtonWhenEnabled<MultiplayerReadyButton>();
|
ClickButtonWhenEnabled<MultiplayerReadyButton>();
|
||||||
AddUntilStep("user is idle (match not started)", () => Client.Room?.Users[0].State == MultiplayerUserState.Idle);
|
AddUntilStep("user is idle (match not started)", () => MultiplayerClient.Room?.Users[0].State == MultiplayerUserState.Idle);
|
||||||
AddAssert("ready button enabled", () => button.ChildrenOfType<OsuButton>().Single().Enabled.Value);
|
AddAssert("ready button enabled", () => button.ChildrenOfType<OsuButton>().Single().Enabled.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,42 +179,42 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
const int users = 10;
|
const int users = 10;
|
||||||
AddStep("setup", () =>
|
AddStep("setup", () =>
|
||||||
{
|
{
|
||||||
Client.TransferHost(Client.Room?.Users[0].UserID ?? 0);
|
MultiplayerClient.TransferHost(MultiplayerClient.Room?.Users[0].UserID ?? 0);
|
||||||
for (int i = 0; i < users; i++)
|
for (int i = 0; i < users; i++)
|
||||||
Client.AddUser(new APIUser { Id = i, Username = "Another user" });
|
MultiplayerClient.AddUser(new APIUser { Id = i, Username = "Another user" });
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!isHost)
|
if (!isHost)
|
||||||
AddStep("transfer host", () => Client.TransferHost(2));
|
AddStep("transfer host", () => MultiplayerClient.TransferHost(2));
|
||||||
|
|
||||||
ClickButtonWhenEnabled<MultiplayerReadyButton>();
|
ClickButtonWhenEnabled<MultiplayerReadyButton>();
|
||||||
|
|
||||||
AddRepeatStep("change user ready state", () =>
|
AddRepeatStep("change user ready state", () =>
|
||||||
{
|
{
|
||||||
Client.ChangeUserState(RNG.Next(0, users), RNG.NextBool() ? MultiplayerUserState.Ready : MultiplayerUserState.Idle);
|
MultiplayerClient.ChangeUserState(RNG.Next(0, users), RNG.NextBool() ? MultiplayerUserState.Ready : MultiplayerUserState.Idle);
|
||||||
}, 20);
|
}, 20);
|
||||||
|
|
||||||
AddRepeatStep("ready all users", () =>
|
AddRepeatStep("ready all users", () =>
|
||||||
{
|
{
|
||||||
var nextUnready = Client.Room?.Users.FirstOrDefault(c => c.State == MultiplayerUserState.Idle);
|
var nextUnready = MultiplayerClient.Room?.Users.FirstOrDefault(c => c.State == MultiplayerUserState.Idle);
|
||||||
if (nextUnready != null)
|
if (nextUnready != null)
|
||||||
Client.ChangeUserState(nextUnready.UserID, MultiplayerUserState.Ready);
|
MultiplayerClient.ChangeUserState(nextUnready.UserID, MultiplayerUserState.Ready);
|
||||||
}, users);
|
}, users);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void verifyGameplayStartFlow()
|
private void verifyGameplayStartFlow()
|
||||||
{
|
{
|
||||||
AddUntilStep("user is ready", () => Client.Room?.Users[0].State == MultiplayerUserState.Ready);
|
AddUntilStep("user is ready", () => MultiplayerClient.Room?.Users[0].State == MultiplayerUserState.Ready);
|
||||||
ClickButtonWhenEnabled<MultiplayerReadyButton>();
|
ClickButtonWhenEnabled<MultiplayerReadyButton>();
|
||||||
AddUntilStep("user waiting for load", () => Client.Room?.Users[0].State == MultiplayerUserState.WaitingForLoad);
|
AddUntilStep("user waiting for load", () => MultiplayerClient.Room?.Users[0].State == MultiplayerUserState.WaitingForLoad);
|
||||||
|
|
||||||
AddAssert("ready button disabled", () => !button.ChildrenOfType<OsuButton>().Single().Enabled.Value);
|
AddAssert("ready button disabled", () => !button.ChildrenOfType<OsuButton>().Single().Enabled.Value);
|
||||||
AddStep("transitioned to gameplay", () => readyClickOperation.Dispose());
|
AddStep("transitioned to gameplay", () => readyClickOperation.Dispose());
|
||||||
|
|
||||||
AddStep("finish gameplay", () =>
|
AddStep("finish gameplay", () =>
|
||||||
{
|
{
|
||||||
Client.ChangeUserState(Client.Room?.Users[0].UserID ?? 0, MultiplayerUserState.Loaded);
|
MultiplayerClient.ChangeUserState(MultiplayerClient.Room?.Users[0].UserID ?? 0, MultiplayerUserState.Loaded);
|
||||||
Client.ChangeUserState(Client.Room?.Users[0].UserID ?? 0, MultiplayerUserState.FinishedPlay);
|
MultiplayerClient.ChangeUserState(MultiplayerClient.Room?.Users[0].UserID ?? 0, MultiplayerUserState.FinishedPlay);
|
||||||
});
|
});
|
||||||
|
|
||||||
AddUntilStep("ready button enabled", () => button.ChildrenOfType<OsuButton>().Single().Enabled.Value);
|
AddUntilStep("ready button enabled", () => button.ChildrenOfType<OsuButton>().Single().Enabled.Value);
|
||||||
|
@ -22,12 +22,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
var beatmapInfo = CreateBeatmap(rulesetInfo).BeatmapInfo;
|
var beatmapInfo = CreateBeatmap(rulesetInfo).BeatmapInfo;
|
||||||
var score = TestResources.CreateTestScoreInfo(beatmapInfo);
|
var score = TestResources.CreateTestScoreInfo(beatmapInfo);
|
||||||
|
|
||||||
PlaylistItem playlistItem = new PlaylistItem
|
Stack.Push(screen = new MultiplayerResultsScreen(score, 1, new PlaylistItem(beatmapInfo)));
|
||||||
{
|
|
||||||
BeatmapID = beatmapInfo.OnlineID,
|
|
||||||
};
|
|
||||||
|
|
||||||
Stack.Push(screen = new MultiplayerResultsScreen(score, 1, playlistItem));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
AddUntilStep("wait for loaded", () => screen.IsLoaded);
|
AddUntilStep("wait for loaded", () => screen.IsLoaded);
|
||||||
|
@ -55,10 +55,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
|
|
||||||
importedSet = beatmaps.GetAllUsableBeatmapSets().First();
|
importedSet = beatmaps.GetAllUsableBeatmapSets().First();
|
||||||
Beatmap.Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First());
|
Beatmap.Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First());
|
||||||
selectedItem.Value = new PlaylistItem
|
selectedItem.Value = new PlaylistItem(Beatmap.Value.BeatmapInfo)
|
||||||
{
|
{
|
||||||
Beatmap = { Value = Beatmap.Value.BeatmapInfo },
|
RulesetID = Beatmap.Value.BeatmapInfo.Ruleset.OnlineID,
|
||||||
Ruleset = { Value = Beatmap.Value.BeatmapInfo.Ruleset },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Child = new FillFlowContainer
|
Child = new FillFlowContainer
|
||||||
@ -78,7 +77,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
|
|
||||||
Task.Run(async () =>
|
Task.Run(async () =>
|
||||||
{
|
{
|
||||||
await Client.ToggleSpectate();
|
await MultiplayerClient.ToggleSpectate();
|
||||||
readyClickOperation.Dispose();
|
readyClickOperation.Dispose();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -94,13 +93,13 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
|
|
||||||
Task.Run(async () =>
|
Task.Run(async () =>
|
||||||
{
|
{
|
||||||
if (Client.IsHost && Client.LocalUser?.State == MultiplayerUserState.Ready)
|
if (MultiplayerClient.IsHost && MultiplayerClient.LocalUser?.State == MultiplayerUserState.Ready)
|
||||||
{
|
{
|
||||||
await Client.StartMatch();
|
await MultiplayerClient.StartMatch();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await Client.ToggleReady();
|
await MultiplayerClient.ToggleReady();
|
||||||
|
|
||||||
readyClickOperation.Dispose();
|
readyClickOperation.Dispose();
|
||||||
});
|
});
|
||||||
@ -115,7 +114,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
[TestCase(MultiplayerRoomState.Playing)]
|
[TestCase(MultiplayerRoomState.Playing)]
|
||||||
public void TestEnabledWhenRoomOpenOrInGameplay(MultiplayerRoomState roomState)
|
public void TestEnabledWhenRoomOpenOrInGameplay(MultiplayerRoomState roomState)
|
||||||
{
|
{
|
||||||
AddStep($"change room to {roomState}", () => Client.ChangeRoomState(roomState));
|
AddStep($"change room to {roomState}", () => MultiplayerClient.ChangeRoomState(roomState));
|
||||||
assertSpectateButtonEnablement(true);
|
assertSpectateButtonEnablement(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,16 +123,16 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
public void TestToggleWhenIdle(MultiplayerUserState initialState)
|
public void TestToggleWhenIdle(MultiplayerUserState initialState)
|
||||||
{
|
{
|
||||||
ClickButtonWhenEnabled<MultiplayerSpectateButton>();
|
ClickButtonWhenEnabled<MultiplayerSpectateButton>();
|
||||||
AddUntilStep("user is spectating", () => Client.Room?.Users[0].State == MultiplayerUserState.Spectating);
|
AddUntilStep("user is spectating", () => MultiplayerClient.Room?.Users[0].State == MultiplayerUserState.Spectating);
|
||||||
|
|
||||||
ClickButtonWhenEnabled<MultiplayerSpectateButton>();
|
ClickButtonWhenEnabled<MultiplayerSpectateButton>();
|
||||||
AddUntilStep("user is idle", () => Client.Room?.Users[0].State == MultiplayerUserState.Idle);
|
AddUntilStep("user is idle", () => MultiplayerClient.Room?.Users[0].State == MultiplayerUserState.Idle);
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase(MultiplayerRoomState.Closed)]
|
[TestCase(MultiplayerRoomState.Closed)]
|
||||||
public void TestDisabledWhenClosed(MultiplayerRoomState roomState)
|
public void TestDisabledWhenClosed(MultiplayerRoomState roomState)
|
||||||
{
|
{
|
||||||
AddStep($"change room to {roomState}", () => Client.ChangeRoomState(roomState));
|
AddStep($"change room to {roomState}", () => MultiplayerClient.ChangeRoomState(roomState));
|
||||||
assertSpectateButtonEnablement(false);
|
assertSpectateButtonEnablement(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,8 +146,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestReadyButtonEnabledWhenHostAndUsersReady()
|
public void TestReadyButtonEnabledWhenHostAndUsersReady()
|
||||||
{
|
{
|
||||||
AddStep("add user", () => Client.AddUser(new APIUser { Id = PLAYER_1_ID }));
|
AddStep("add user", () => MultiplayerClient.AddUser(new APIUser { Id = PLAYER_1_ID }));
|
||||||
AddStep("set user ready", () => Client.ChangeUserState(PLAYER_1_ID, MultiplayerUserState.Ready));
|
AddStep("set user ready", () => MultiplayerClient.ChangeUserState(PLAYER_1_ID, MultiplayerUserState.Ready));
|
||||||
|
|
||||||
ClickButtonWhenEnabled<MultiplayerSpectateButton>();
|
ClickButtonWhenEnabled<MultiplayerSpectateButton>();
|
||||||
assertReadyButtonEnablement(true);
|
assertReadyButtonEnablement(true);
|
||||||
@ -159,11 +158,11 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
{
|
{
|
||||||
AddStep("add user and transfer host", () =>
|
AddStep("add user and transfer host", () =>
|
||||||
{
|
{
|
||||||
Client.AddUser(new APIUser { Id = PLAYER_1_ID });
|
MultiplayerClient.AddUser(new APIUser { Id = PLAYER_1_ID });
|
||||||
Client.TransferHost(PLAYER_1_ID);
|
MultiplayerClient.TransferHost(PLAYER_1_ID);
|
||||||
});
|
});
|
||||||
|
|
||||||
AddStep("set user ready", () => Client.ChangeUserState(PLAYER_1_ID, MultiplayerUserState.Ready));
|
AddStep("set user ready", () => MultiplayerClient.ChangeUserState(PLAYER_1_ID, MultiplayerUserState.Ready));
|
||||||
|
|
||||||
ClickButtonWhenEnabled<MultiplayerSpectateButton>();
|
ClickButtonWhenEnabled<MultiplayerSpectateButton>();
|
||||||
assertReadyButtonEnablement(false);
|
assertReadyButtonEnablement(false);
|
||||||
|
@ -26,18 +26,13 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
var beatmapInfo = CreateBeatmap(rulesetInfo).BeatmapInfo;
|
var beatmapInfo = CreateBeatmap(rulesetInfo).BeatmapInfo;
|
||||||
var score = TestResources.CreateTestScoreInfo(beatmapInfo);
|
var score = TestResources.CreateTestScoreInfo(beatmapInfo);
|
||||||
|
|
||||||
PlaylistItem playlistItem = new PlaylistItem
|
|
||||||
{
|
|
||||||
BeatmapID = beatmapInfo.OnlineID,
|
|
||||||
};
|
|
||||||
|
|
||||||
SortedDictionary<int, BindableInt> teamScores = new SortedDictionary<int, BindableInt>
|
SortedDictionary<int, BindableInt> teamScores = new SortedDictionary<int, BindableInt>
|
||||||
{
|
{
|
||||||
{ 0, new BindableInt(team1Score) },
|
{ 0, new BindableInt(team1Score) },
|
||||||
{ 1, new BindableInt(team2Score) }
|
{ 1, new BindableInt(team2Score) }
|
||||||
};
|
};
|
||||||
|
|
||||||
Stack.Push(screen = new MultiplayerTeamResultsScreen(score, 1, playlistItem, teamScores));
|
Stack.Push(screen = new MultiplayerTeamResultsScreen(score, 1, new PlaylistItem(beatmapInfo), teamScores));
|
||||||
});
|
});
|
||||||
|
|
||||||
AddUntilStep("wait for loaded", () => screen.IsLoaded);
|
AddUntilStep("wait for loaded", () => screen.IsLoaded);
|
||||||
|
@ -4,33 +4,29 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Allocation;
|
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Beatmaps.Drawables;
|
|
||||||
using osu.Game.Database;
|
|
||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
using osu.Game.Models;
|
using osu.Game.Models;
|
||||||
|
using osu.Game.Online.API;
|
||||||
using osu.Game.Online.Rooms;
|
using osu.Game.Online.Rooms;
|
||||||
using osu.Game.Rulesets.Osu;
|
using osu.Game.Rulesets.Osu;
|
||||||
using osu.Game.Rulesets.Osu.Mods;
|
using osu.Game.Rulesets.Osu.Mods;
|
||||||
using osu.Game.Screens.OnlinePlay;
|
using osu.Game.Screens.OnlinePlay;
|
||||||
using osu.Game.Screens.OnlinePlay.Playlists;
|
using osu.Game.Screens.OnlinePlay.Playlists;
|
||||||
using osu.Game.Tests.Beatmaps;
|
using osu.Game.Tests.Beatmaps;
|
||||||
|
using osu.Game.Tests.Visual.OnlinePlay;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Input;
|
using osuTK.Input;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Multiplayer
|
namespace osu.Game.Tests.Visual.Multiplayer
|
||||||
{
|
{
|
||||||
public class TestScenePlaylistsRoomSettingsPlaylist : OsuManualInputManagerTestScene
|
public class TestScenePlaylistsRoomSettingsPlaylist : OnlinePlayTestScene
|
||||||
{
|
{
|
||||||
private TestPlaylist playlist;
|
private TestPlaylist playlist;
|
||||||
|
|
||||||
[Cached(typeof(UserLookupCache))]
|
|
||||||
private readonly TestUserLookupCache userLookupCache = new TestUserLookupCache();
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestItemRemovedOnDeletion()
|
public void TestItemRemovedOnDeletion()
|
||||||
{
|
{
|
||||||
@ -110,18 +106,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
AddAssert("item 0 is selected", () => playlist.SelectedItem.Value == playlist.Items[0]);
|
AddAssert("item 0 is selected", () => playlist.SelectedItem.Value == playlist.Items[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void TestChangeBeatmapAndRemove()
|
|
||||||
{
|
|
||||||
createPlaylist();
|
|
||||||
|
|
||||||
AddStep("change beatmap of first item", () => playlist.Items[0].BeatmapID = 30);
|
|
||||||
moveToDeleteButton(0);
|
|
||||||
AddStep("click delete button", () => InputManager.Click(MouseButton.Left));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void moveToItem(int index, Vector2? offset = null)
|
private void moveToItem(int index, Vector2? offset = null)
|
||||||
=> AddStep($"move mouse to item {index}", () => InputManager.MoveMouseTo(playlist.ChildrenOfType<DifficultyIcon>().ElementAt(index), offset));
|
=> AddStep($"move mouse to item {index}", () => InputManager.MoveMouseTo(playlist.ChildrenOfType<DrawableRoomPlaylistItem>().ElementAt(index), offset));
|
||||||
|
|
||||||
private void moveToDeleteButton(int index, Vector2? offset = null) => AddStep($"move mouse to delete button {index}", () =>
|
private void moveToDeleteButton(int index, Vector2? offset = null) => AddStep($"move mouse to delete button {index}", () =>
|
||||||
{
|
{
|
||||||
@ -142,31 +128,27 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
|
|
||||||
for (int i = 0; i < 20; i++)
|
for (int i = 0; i < 20; i++)
|
||||||
{
|
{
|
||||||
playlist.Items.Add(new PlaylistItem
|
playlist.Items.Add(new PlaylistItem(i % 2 == 1
|
||||||
|
? new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo
|
||||||
|
: new BeatmapInfo
|
||||||
|
{
|
||||||
|
Metadata = new BeatmapMetadata
|
||||||
|
{
|
||||||
|
Artist = "Artist",
|
||||||
|
Author = new RealmUser { Username = "Creator name here" },
|
||||||
|
Title = "Long title used to check background colour",
|
||||||
|
},
|
||||||
|
BeatmapSet = new BeatmapSetInfo()
|
||||||
|
})
|
||||||
{
|
{
|
||||||
ID = i,
|
ID = i,
|
||||||
OwnerID = 2,
|
OwnerID = 2,
|
||||||
Beatmap =
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID,
|
||||||
|
RequiredMods = new[]
|
||||||
{
|
{
|
||||||
Value = i % 2 == 1
|
new APIMod(new OsuModHardRock()),
|
||||||
? new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo
|
new APIMod(new OsuModDoubleTime()),
|
||||||
: new BeatmapInfo
|
new APIMod(new OsuModAutoplay())
|
||||||
{
|
|
||||||
Metadata = new BeatmapMetadata
|
|
||||||
{
|
|
||||||
Artist = "Artist",
|
|
||||||
Author = new RealmUser { Username = "Creator name here" },
|
|
||||||
Title = "Long title used to check background colour",
|
|
||||||
},
|
|
||||||
BeatmapSet = new BeatmapSetInfo()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Ruleset = { Value = new OsuRuleset().RulesetInfo },
|
|
||||||
RequiredMods =
|
|
||||||
{
|
|
||||||
new OsuModHardRock(),
|
|
||||||
new OsuModDoubleTime(),
|
|
||||||
new OsuModAutoplay()
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -115,8 +115,17 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
AddStep("change mod rate", () => ((OsuModDoubleTime)SelectedMods.Value[0]).SpeedChange.Value = 2);
|
AddStep("change mod rate", () => ((OsuModDoubleTime)SelectedMods.Value[0]).SpeedChange.Value = 2);
|
||||||
AddStep("create item", () => songSelect.BeatmapDetails.CreateNewItem());
|
AddStep("create item", () => songSelect.BeatmapDetails.CreateNewItem());
|
||||||
|
|
||||||
AddAssert("item 1 has rate 1.5", () => Precision.AlmostEquals(1.5, ((OsuModDoubleTime)SelectedRoom.Value.Playlist.First().RequiredMods[0]).SpeedChange.Value));
|
AddAssert("item 1 has rate 1.5", () =>
|
||||||
AddAssert("item 2 has rate 2", () => Precision.AlmostEquals(2, ((OsuModDoubleTime)SelectedRoom.Value.Playlist.Last().RequiredMods[0]).SpeedChange.Value));
|
{
|
||||||
|
var mod = (OsuModDoubleTime)SelectedRoom.Value.Playlist.First().RequiredMods[0].ToMod(new OsuRuleset());
|
||||||
|
return Precision.AlmostEquals(1.5, mod.SpeedChange.Value);
|
||||||
|
});
|
||||||
|
|
||||||
|
AddAssert("item 2 has rate 2", () =>
|
||||||
|
{
|
||||||
|
var mod = (OsuModDoubleTime)SelectedRoom.Value.Playlist.Last().RequiredMods[0].ToMod(new OsuRuleset());
|
||||||
|
return Precision.AlmostEquals(2, mod.SpeedChange.Value);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -138,7 +147,11 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
AddStep("create item", () => songSelect.BeatmapDetails.CreateNewItem());
|
AddStep("create item", () => songSelect.BeatmapDetails.CreateNewItem());
|
||||||
|
|
||||||
AddStep("change stored mod rate", () => mod.SpeedChange.Value = 2);
|
AddStep("change stored mod rate", () => mod.SpeedChange.Value = 2);
|
||||||
AddAssert("item has rate 1.5", () => Precision.AlmostEquals(1.5, ((OsuModDoubleTime)SelectedRoom.Value.Playlist.First().RequiredMods[0]).SpeedChange.Value));
|
AddAssert("item has rate 1.5", () =>
|
||||||
|
{
|
||||||
|
var m = (OsuModDoubleTime)SelectedRoom.Value.Playlist.First().RequiredMods[0].ToMod(new OsuRuleset());
|
||||||
|
return Precision.AlmostEquals(1.5, m.SpeedChange.Value);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TestPlaylistsSongSelect : PlaylistsSongSelect
|
private class TestPlaylistsSongSelect : PlaylistsSongSelect
|
||||||
|
@ -25,14 +25,14 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
{
|
{
|
||||||
AddStep("add user", () =>
|
AddStep("add user", () =>
|
||||||
{
|
{
|
||||||
Client.AddUser(new APIUser
|
MultiplayerClient.AddUser(new APIUser
|
||||||
{
|
{
|
||||||
Id = 2,
|
Id = 2,
|
||||||
Statistics = { GlobalRank = 1234 }
|
Statistics = { GlobalRank = 1234 }
|
||||||
});
|
});
|
||||||
|
|
||||||
// Remove the local user so only the one above is displayed.
|
// Remove the local user so only the one above is displayed.
|
||||||
Client.RemoveUser(API.LocalUser.Value);
|
MultiplayerClient.RemoveUser(API.LocalUser.Value);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,26 +41,26 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
{
|
{
|
||||||
AddStep("add users", () =>
|
AddStep("add users", () =>
|
||||||
{
|
{
|
||||||
Client.AddUser(new APIUser
|
MultiplayerClient.AddUser(new APIUser
|
||||||
{
|
{
|
||||||
Id = 2,
|
Id = 2,
|
||||||
Statistics = { GlobalRank = 1234 }
|
Statistics = { GlobalRank = 1234 }
|
||||||
});
|
});
|
||||||
|
|
||||||
Client.AddUser(new APIUser
|
MultiplayerClient.AddUser(new APIUser
|
||||||
{
|
{
|
||||||
Id = 3,
|
Id = 3,
|
||||||
Statistics = { GlobalRank = 3333 }
|
Statistics = { GlobalRank = 3333 }
|
||||||
});
|
});
|
||||||
|
|
||||||
Client.AddUser(new APIUser
|
MultiplayerClient.AddUser(new APIUser
|
||||||
{
|
{
|
||||||
Id = 4,
|
Id = 4,
|
||||||
Statistics = { GlobalRank = 4321 }
|
Statistics = { GlobalRank = 4321 }
|
||||||
});
|
});
|
||||||
|
|
||||||
// Remove the local user so only the ones above are displayed.
|
// Remove the local user so only the ones above are displayed.
|
||||||
Client.RemoveUser(API.LocalUser.Value);
|
MultiplayerClient.RemoveUser(API.LocalUser.Value);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,20 +75,20 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
{
|
{
|
||||||
AddStep("add users", () =>
|
AddStep("add users", () =>
|
||||||
{
|
{
|
||||||
Client.AddUser(new APIUser
|
MultiplayerClient.AddUser(new APIUser
|
||||||
{
|
{
|
||||||
Id = 2,
|
Id = 2,
|
||||||
Statistics = { GlobalRank = min }
|
Statistics = { GlobalRank = min }
|
||||||
});
|
});
|
||||||
|
|
||||||
Client.AddUser(new APIUser
|
MultiplayerClient.AddUser(new APIUser
|
||||||
{
|
{
|
||||||
Id = 3,
|
Id = 3,
|
||||||
Statistics = { GlobalRank = max }
|
Statistics = { GlobalRank = max }
|
||||||
});
|
});
|
||||||
|
|
||||||
// Remove the local user so only the ones above are displayed.
|
// Remove the local user so only the ones above are displayed.
|
||||||
Client.RemoveUser(API.LocalUser.Value);
|
MultiplayerClient.RemoveUser(API.LocalUser.Value);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,8 +31,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
{
|
{
|
||||||
SelectedRoom.Value.Playlist.AddRange(new[]
|
SelectedRoom.Value.Playlist.AddRange(new[]
|
||||||
{
|
{
|
||||||
new PlaylistItem { Beatmap = { Value = new BeatmapInfo { StarRating = min } } },
|
new PlaylistItem(new BeatmapInfo { StarRating = min }),
|
||||||
new PlaylistItem { Beatmap = { Value = new BeatmapInfo { StarRating = max } } },
|
new PlaylistItem(new BeatmapInfo { StarRating = max }),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,6 @@ using osu.Framework.Extensions;
|
|||||||
using osu.Framework.Platform;
|
using osu.Framework.Platform;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Database;
|
|
||||||
using osu.Game.Online.API.Requests.Responses;
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
using osu.Game.Online.Multiplayer;
|
using osu.Game.Online.Multiplayer;
|
||||||
using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus;
|
using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus;
|
||||||
@ -34,10 +33,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
|
|
||||||
private TestMultiplayerComponents multiplayerComponents;
|
private TestMultiplayerComponents multiplayerComponents;
|
||||||
|
|
||||||
private TestMultiplayerClient client => multiplayerComponents.Client;
|
private TestMultiplayerClient multiplayerClient => multiplayerComponents.MultiplayerClient;
|
||||||
|
|
||||||
[Cached(typeof(UserLookupCache))]
|
|
||||||
private UserLookupCache lookupCache = new TestUserLookupCache();
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(GameHost host, AudioManager audio)
|
private void load(GameHost host, AudioManager audio)
|
||||||
@ -71,16 +67,15 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
Type = { Value = MatchType.TeamVersus },
|
Type = { Value = MatchType.TeamVersus },
|
||||||
Playlist =
|
Playlist =
|
||||||
{
|
{
|
||||||
new PlaylistItem
|
new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
|
||||||
{
|
{
|
||||||
Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
|
||||||
Ruleset = { Value = new OsuRuleset().RulesetInfo },
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
AddUntilStep("room type is team vs", () => client.Room?.Settings.MatchType == MatchType.TeamVersus);
|
AddUntilStep("room type is team vs", () => multiplayerClient.Room?.Settings.MatchType == MatchType.TeamVersus);
|
||||||
AddAssert("user state arrived", () => client.Room?.Users.FirstOrDefault()?.MatchState is TeamVersusUserState);
|
AddAssert("user state arrived", () => multiplayerClient.Room?.Users.FirstOrDefault()?.MatchState is TeamVersusUserState);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -92,33 +87,32 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
Type = { Value = MatchType.TeamVersus },
|
Type = { Value = MatchType.TeamVersus },
|
||||||
Playlist =
|
Playlist =
|
||||||
{
|
{
|
||||||
new PlaylistItem
|
new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
|
||||||
{
|
{
|
||||||
Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
|
||||||
Ruleset = { Value = new OsuRuleset().RulesetInfo },
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
AddAssert("user on team 0", () => (client.Room?.Users.FirstOrDefault()?.MatchState as TeamVersusUserState)?.TeamID == 0);
|
AddAssert("user on team 0", () => (multiplayerClient.Room?.Users.FirstOrDefault()?.MatchState as TeamVersusUserState)?.TeamID == 0);
|
||||||
AddStep("add another user", () => client.AddUser(new APIUser { Username = "otheruser", Id = 44 }));
|
AddStep("add another user", () => multiplayerClient.AddUser(new APIUser { Username = "otheruser", Id = 44 }));
|
||||||
|
|
||||||
AddStep("press own button", () =>
|
AddStep("press own button", () =>
|
||||||
{
|
{
|
||||||
InputManager.MoveMouseTo(multiplayerComponents.ChildrenOfType<TeamDisplay>().First());
|
InputManager.MoveMouseTo(multiplayerComponents.ChildrenOfType<TeamDisplay>().First());
|
||||||
InputManager.Click(MouseButton.Left);
|
InputManager.Click(MouseButton.Left);
|
||||||
});
|
});
|
||||||
AddAssert("user on team 1", () => (client.Room?.Users.FirstOrDefault()?.MatchState as TeamVersusUserState)?.TeamID == 1);
|
AddAssert("user on team 1", () => (multiplayerClient.Room?.Users.FirstOrDefault()?.MatchState as TeamVersusUserState)?.TeamID == 1);
|
||||||
|
|
||||||
AddStep("press own button again", () => InputManager.Click(MouseButton.Left));
|
AddStep("press own button again", () => InputManager.Click(MouseButton.Left));
|
||||||
AddAssert("user on team 0", () => (client.Room?.Users.FirstOrDefault()?.MatchState as TeamVersusUserState)?.TeamID == 0);
|
AddAssert("user on team 0", () => (multiplayerClient.Room?.Users.FirstOrDefault()?.MatchState as TeamVersusUserState)?.TeamID == 0);
|
||||||
|
|
||||||
AddStep("press other user's button", () =>
|
AddStep("press other user's button", () =>
|
||||||
{
|
{
|
||||||
InputManager.MoveMouseTo(multiplayerComponents.ChildrenOfType<TeamDisplay>().ElementAt(1));
|
InputManager.MoveMouseTo(multiplayerComponents.ChildrenOfType<TeamDisplay>().ElementAt(1));
|
||||||
InputManager.Click(MouseButton.Left);
|
InputManager.Click(MouseButton.Left);
|
||||||
});
|
});
|
||||||
AddAssert("user still on team 0", () => (client.Room?.Users.FirstOrDefault()?.MatchState as TeamVersusUserState)?.TeamID == 0);
|
AddAssert("user still on team 0", () => (multiplayerClient.Room?.Users.FirstOrDefault()?.MatchState as TeamVersusUserState)?.TeamID == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -130,22 +124,21 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
Type = { Value = MatchType.HeadToHead },
|
Type = { Value = MatchType.HeadToHead },
|
||||||
Playlist =
|
Playlist =
|
||||||
{
|
{
|
||||||
new PlaylistItem
|
new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
|
||||||
{
|
{
|
||||||
Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID,
|
||||||
Ruleset = { Value = new OsuRuleset().RulesetInfo },
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
AddUntilStep("match type head to head", () => client.APIRoom?.Type.Value == MatchType.HeadToHead);
|
AddUntilStep("match type head to head", () => multiplayerClient.APIRoom?.Type.Value == MatchType.HeadToHead);
|
||||||
|
|
||||||
AddStep("change match type", () => client.ChangeSettings(new MultiplayerRoomSettings
|
AddStep("change match type", () => multiplayerClient.ChangeSettings(new MultiplayerRoomSettings
|
||||||
{
|
{
|
||||||
MatchType = MatchType.TeamVersus
|
MatchType = MatchType.TeamVersus
|
||||||
}));
|
}).WaitSafely());
|
||||||
|
|
||||||
AddUntilStep("api room updated to team versus", () => client.APIRoom?.Type.Value == MatchType.TeamVersus);
|
AddUntilStep("api room updated to team versus", () => multiplayerClient.APIRoom?.Type.Value == MatchType.TeamVersus);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -156,21 +149,20 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
Name = { Value = "Test Room" },
|
Name = { Value = "Test Room" },
|
||||||
Playlist =
|
Playlist =
|
||||||
{
|
{
|
||||||
new PlaylistItem
|
new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
|
||||||
{
|
{
|
||||||
Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID,
|
||||||
Ruleset = { Value = new OsuRuleset().RulesetInfo },
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
AddUntilStep("room type is head to head", () => client.Room?.Settings.MatchType == MatchType.HeadToHead);
|
AddUntilStep("room type is head to head", () => multiplayerClient.Room?.Settings.MatchType == MatchType.HeadToHead);
|
||||||
|
|
||||||
AddUntilStep("team displays are not displaying teams", () => multiplayerComponents.ChildrenOfType<TeamDisplay>().All(d => d.DisplayedTeam == null));
|
AddUntilStep("team displays are not displaying teams", () => multiplayerComponents.ChildrenOfType<TeamDisplay>().All(d => d.DisplayedTeam == null));
|
||||||
|
|
||||||
AddStep("change to team vs", () => client.ChangeSettings(matchType: MatchType.TeamVersus));
|
AddStep("change to team vs", () => multiplayerClient.ChangeSettings(matchType: MatchType.TeamVersus));
|
||||||
|
|
||||||
AddUntilStep("room type is team vs", () => client.Room?.Settings.MatchType == MatchType.TeamVersus);
|
AddUntilStep("room type is team vs", () => multiplayerClient.Room?.Settings.MatchType == MatchType.TeamVersus);
|
||||||
|
|
||||||
AddUntilStep("team displays are displaying teams", () => multiplayerComponents.ChildrenOfType<TeamDisplay>().All(d => d.DisplayedTeam != null));
|
AddUntilStep("team displays are displaying teams", () => multiplayerComponents.ChildrenOfType<TeamDisplay>().All(d => d.DisplayedTeam != null));
|
||||||
}
|
}
|
||||||
@ -189,7 +181,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
InputManager.Click(MouseButton.Left);
|
InputManager.Click(MouseButton.Left);
|
||||||
});
|
});
|
||||||
|
|
||||||
AddUntilStep("wait for join", () => client.RoomJoined);
|
AddUntilStep("wait for join", () => multiplayerClient.RoomJoined);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
43
osu.Game.Tests/Visual/Navigation/TestEFToRealmMigration.cs
Normal file
43
osu.Game.Tests/Visual/Navigation/TestEFToRealmMigration.cs
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
// 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.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Database;
|
||||||
|
using osu.Game.Models;
|
||||||
|
using osu.Game.Scoring;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
using osu.Game.Tests.Resources;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.Navigation
|
||||||
|
{
|
||||||
|
public class TestEFToRealmMigration : OsuGameTestScene
|
||||||
|
{
|
||||||
|
public override void RecycleLocalStorage(bool isDisposing)
|
||||||
|
{
|
||||||
|
base.RecycleLocalStorage(isDisposing);
|
||||||
|
|
||||||
|
if (isDisposing)
|
||||||
|
return;
|
||||||
|
|
||||||
|
using (var outStream = LocalStorage.GetStream(DatabaseContextFactory.DATABASE_NAME, FileAccess.Write, FileMode.Create))
|
||||||
|
using (var stream = TestResources.OpenResource(DatabaseContextFactory.DATABASE_NAME))
|
||||||
|
stream.CopyTo(outStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestMigration()
|
||||||
|
{
|
||||||
|
// Numbers are taken from the test database (see commit f03de16ee5a46deac3b5f2ca1edfba5c4c5dca7d).
|
||||||
|
AddAssert("Check beatmaps", () => Game.Dependencies.Get<RealmAccess>().Run(r => r.All<BeatmapSetInfo>().Count(s => !s.Protected) == 1));
|
||||||
|
AddAssert("Check skins", () => Game.Dependencies.Get<RealmAccess>().Run(r => r.All<SkinInfo>().Count(s => !s.Protected) == 1));
|
||||||
|
AddAssert("Check scores", () => Game.Dependencies.Get<RealmAccess>().Run(r => r.All<ScoreInfo>().Count() == 1));
|
||||||
|
|
||||||
|
// One extra file is created during realm migration / startup due to the circles intro import.
|
||||||
|
AddAssert("Check files", () => Game.Dependencies.Get<RealmAccess>().Run(r => r.All<RealmFile>().Count() == 271));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -49,7 +49,7 @@ namespace osu.Game.Tests.Visual.Playlists
|
|||||||
AddStep("set name", () => SelectedRoom.Value.Name.Value = "Room name");
|
AddStep("set name", () => SelectedRoom.Value.Name.Value = "Room name");
|
||||||
AddAssert("button disabled", () => !settings.ApplyButton.Enabled.Value);
|
AddAssert("button disabled", () => !settings.ApplyButton.Enabled.Value);
|
||||||
|
|
||||||
AddStep("set beatmap", () => SelectedRoom.Value.Playlist.Add(new PlaylistItem { Beatmap = { Value = CreateBeatmap(Ruleset.Value).BeatmapInfo } }));
|
AddStep("set beatmap", () => SelectedRoom.Value.Playlist.Add(new PlaylistItem(CreateBeatmap(Ruleset.Value).BeatmapInfo)));
|
||||||
AddAssert("button enabled", () => settings.ApplyButton.Enabled.Value);
|
AddAssert("button enabled", () => settings.ApplyButton.Enabled.Value);
|
||||||
|
|
||||||
AddStep("clear name", () => SelectedRoom.Value.Name.Value = "");
|
AddStep("clear name", () => SelectedRoom.Value.Name.Value = "");
|
||||||
@ -68,7 +68,7 @@ namespace osu.Game.Tests.Visual.Playlists
|
|||||||
{
|
{
|
||||||
settings.NameField.Current.Value = expected_name;
|
settings.NameField.Current.Value = expected_name;
|
||||||
settings.DurationField.Current.Value = expectedDuration;
|
settings.DurationField.Current.Value = expectedDuration;
|
||||||
SelectedRoom.Value.Playlist.Add(new PlaylistItem { Beatmap = { Value = CreateBeatmap(Ruleset.Value).BeatmapInfo } });
|
SelectedRoom.Value.Playlist.Add(new PlaylistItem(CreateBeatmap(Ruleset.Value).BeatmapInfo));
|
||||||
|
|
||||||
RoomManager.CreateRequested = r =>
|
RoomManager.CreateRequested = r =>
|
||||||
{
|
{
|
||||||
@ -94,7 +94,7 @@ namespace osu.Game.Tests.Visual.Playlists
|
|||||||
var beatmap = CreateBeatmap(Ruleset.Value).BeatmapInfo;
|
var beatmap = CreateBeatmap(Ruleset.Value).BeatmapInfo;
|
||||||
|
|
||||||
SelectedRoom.Value.Name.Value = "Test Room";
|
SelectedRoom.Value.Name.Value = "Test Room";
|
||||||
SelectedRoom.Value.Playlist.Add(new PlaylistItem { Beatmap = { Value = beatmap } });
|
SelectedRoom.Value.Playlist.Add(new PlaylistItem(beatmap));
|
||||||
|
|
||||||
errorMessage = $"{not_found_prefix} {beatmap.OnlineID}";
|
errorMessage = $"{not_found_prefix} {beatmap.OnlineID}";
|
||||||
|
|
||||||
@ -121,7 +121,7 @@ namespace osu.Game.Tests.Visual.Playlists
|
|||||||
AddStep("setup", () =>
|
AddStep("setup", () =>
|
||||||
{
|
{
|
||||||
SelectedRoom.Value.Name.Value = "Test Room";
|
SelectedRoom.Value.Name.Value = "Test Room";
|
||||||
SelectedRoom.Value.Playlist.Add(new PlaylistItem { Beatmap = { Value = CreateBeatmap(Ruleset.Value).BeatmapInfo } });
|
SelectedRoom.Value.Playlist.Add(new PlaylistItem(CreateBeatmap(Ruleset.Value).BeatmapInfo));
|
||||||
|
|
||||||
RoomManager.CreateRequested = _ => failText;
|
RoomManager.CreateRequested = _ => failText;
|
||||||
});
|
});
|
||||||
|
@ -165,10 +165,9 @@ namespace osu.Game.Tests.Visual.Playlists
|
|||||||
{
|
{
|
||||||
AddStep("load results", () =>
|
AddStep("load results", () =>
|
||||||
{
|
{
|
||||||
LoadScreen(resultsScreen = new TestResultsScreen(getScore?.Invoke(), 1, new PlaylistItem
|
LoadScreen(resultsScreen = new TestResultsScreen(getScore?.Invoke(), 1, new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo)
|
||||||
{
|
{
|
||||||
Beatmap = { Value = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo },
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
|
||||||
Ruleset = { Value = new OsuRuleset().RulesetInfo }
|
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -64,10 +64,9 @@ namespace osu.Game.Tests.Visual.Playlists
|
|||||||
room.Host.Value = API.LocalUser.Value;
|
room.Host.Value = API.LocalUser.Value;
|
||||||
room.RecentParticipants.Add(room.Host.Value);
|
room.RecentParticipants.Add(room.Host.Value);
|
||||||
room.EndDate.Value = DateTimeOffset.Now.AddMinutes(5);
|
room.EndDate.Value = DateTimeOffset.Now.AddMinutes(5);
|
||||||
room.Playlist.Add(new PlaylistItem
|
room.Playlist.Add(new PlaylistItem(importedBeatmap.Beatmaps.First())
|
||||||
{
|
{
|
||||||
Beatmap = { Value = importedBeatmap.Beatmaps.First() },
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
|
||||||
Ruleset = { Value = new OsuRuleset().RulesetInfo }
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -89,10 +88,9 @@ namespace osu.Game.Tests.Visual.Playlists
|
|||||||
room.Host.Value = API.LocalUser.Value;
|
room.Host.Value = API.LocalUser.Value;
|
||||||
room.RecentParticipants.Add(room.Host.Value);
|
room.RecentParticipants.Add(room.Host.Value);
|
||||||
room.EndDate.Value = DateTimeOffset.Now.AddMinutes(5);
|
room.EndDate.Value = DateTimeOffset.Now.AddMinutes(5);
|
||||||
room.Playlist.Add(new PlaylistItem
|
room.Playlist.Add(new PlaylistItem(importedBeatmap.Beatmaps.First())
|
||||||
{
|
{
|
||||||
Beatmap = { Value = importedBeatmap.Beatmaps.First() },
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
|
||||||
Ruleset = { Value = new OsuRuleset().RulesetInfo }
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -106,10 +104,9 @@ namespace osu.Game.Tests.Visual.Playlists
|
|||||||
{
|
{
|
||||||
room.Name.Value = "my awesome room";
|
room.Name.Value = "my awesome room";
|
||||||
room.Host.Value = API.LocalUser.Value;
|
room.Host.Value = API.LocalUser.Value;
|
||||||
room.Playlist.Add(new PlaylistItem
|
room.Playlist.Add(new PlaylistItem(importedBeatmap.Beatmaps.First())
|
||||||
{
|
{
|
||||||
Beatmap = { Value = importedBeatmap.Beatmaps.First() },
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
|
||||||
Ruleset = { Value = new OsuRuleset().RulesetInfo }
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -158,22 +155,18 @@ namespace osu.Game.Tests.Visual.Playlists
|
|||||||
{
|
{
|
||||||
room.Name.Value = "my awesome room";
|
room.Name.Value = "my awesome room";
|
||||||
room.Host.Value = API.LocalUser.Value;
|
room.Host.Value = API.LocalUser.Value;
|
||||||
room.Playlist.Add(new PlaylistItem
|
room.Playlist.Add(new PlaylistItem(new BeatmapInfo
|
||||||
{
|
{
|
||||||
Beatmap =
|
MD5Hash = realHash,
|
||||||
|
OnlineID = realOnlineId,
|
||||||
|
Metadata = new BeatmapMetadata(),
|
||||||
|
BeatmapSet = new BeatmapSetInfo
|
||||||
{
|
{
|
||||||
Value = new BeatmapInfo
|
OnlineID = realOnlineSetId,
|
||||||
{
|
}
|
||||||
MD5Hash = realHash,
|
})
|
||||||
OnlineID = realOnlineId,
|
{
|
||||||
Metadata = new BeatmapMetadata(),
|
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
|
||||||
BeatmapSet = new BeatmapSetInfo
|
|
||||||
{
|
|
||||||
OnlineID = realOnlineSetId,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Ruleset = { Value = new OsuRuleset().RulesetInfo }
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -197,6 +197,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
Accuracy = 1,
|
Accuracy = 1,
|
||||||
MaxCombo = 244,
|
MaxCombo = 244,
|
||||||
TotalScore = 1707827,
|
TotalScore = 1707827,
|
||||||
|
Date = DateTime.Now,
|
||||||
Mods = new Mod[]
|
Mods = new Mod[]
|
||||||
{
|
{
|
||||||
new OsuModHidden(),
|
new OsuModHidden(),
|
||||||
@ -234,6 +235,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
Accuracy = 1,
|
Accuracy = 1,
|
||||||
MaxCombo = 244,
|
MaxCombo = 244,
|
||||||
TotalScore = 1707827,
|
TotalScore = 1707827,
|
||||||
|
Date = DateTime.Now.AddSeconds(-30),
|
||||||
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
||||||
BeatmapInfo = beatmapInfo,
|
BeatmapInfo = beatmapInfo,
|
||||||
Ruleset = new OsuRuleset().RulesetInfo,
|
Ruleset = new OsuRuleset().RulesetInfo,
|
||||||
@ -254,6 +256,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
Accuracy = 1,
|
Accuracy = 1,
|
||||||
MaxCombo = 244,
|
MaxCombo = 244,
|
||||||
TotalScore = 1707827,
|
TotalScore = 1707827,
|
||||||
|
Date = DateTime.Now.AddSeconds(-70),
|
||||||
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
||||||
BeatmapInfo = beatmapInfo,
|
BeatmapInfo = beatmapInfo,
|
||||||
Ruleset = new OsuRuleset().RulesetInfo,
|
Ruleset = new OsuRuleset().RulesetInfo,
|
||||||
@ -275,6 +278,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
Accuracy = 1,
|
Accuracy = 1,
|
||||||
MaxCombo = 244,
|
MaxCombo = 244,
|
||||||
TotalScore = 1707827,
|
TotalScore = 1707827,
|
||||||
|
Date = DateTime.Now.AddMinutes(-40),
|
||||||
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
||||||
BeatmapInfo = beatmapInfo,
|
BeatmapInfo = beatmapInfo,
|
||||||
Ruleset = new OsuRuleset().RulesetInfo,
|
Ruleset = new OsuRuleset().RulesetInfo,
|
||||||
@ -296,6 +300,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
Accuracy = 1,
|
Accuracy = 1,
|
||||||
MaxCombo = 244,
|
MaxCombo = 244,
|
||||||
TotalScore = 1707827,
|
TotalScore = 1707827,
|
||||||
|
Date = DateTime.Now.AddHours(-2),
|
||||||
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
||||||
BeatmapInfo = beatmapInfo,
|
BeatmapInfo = beatmapInfo,
|
||||||
Ruleset = new OsuRuleset().RulesetInfo,
|
Ruleset = new OsuRuleset().RulesetInfo,
|
||||||
@ -317,6 +322,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
Accuracy = 0.9826,
|
Accuracy = 0.9826,
|
||||||
MaxCombo = 244,
|
MaxCombo = 244,
|
||||||
TotalScore = 1707827,
|
TotalScore = 1707827,
|
||||||
|
Date = DateTime.Now.AddHours(-25),
|
||||||
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
||||||
BeatmapInfo = beatmapInfo,
|
BeatmapInfo = beatmapInfo,
|
||||||
Ruleset = new OsuRuleset().RulesetInfo,
|
Ruleset = new OsuRuleset().RulesetInfo,
|
||||||
@ -338,6 +344,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
Accuracy = 0.9654,
|
Accuracy = 0.9654,
|
||||||
MaxCombo = 244,
|
MaxCombo = 244,
|
||||||
TotalScore = 1707827,
|
TotalScore = 1707827,
|
||||||
|
Date = DateTime.Now.AddHours(-50),
|
||||||
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
||||||
BeatmapInfo = beatmapInfo,
|
BeatmapInfo = beatmapInfo,
|
||||||
Ruleset = new OsuRuleset().RulesetInfo,
|
Ruleset = new OsuRuleset().RulesetInfo,
|
||||||
@ -359,6 +366,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
Accuracy = 0.6025,
|
Accuracy = 0.6025,
|
||||||
MaxCombo = 244,
|
MaxCombo = 244,
|
||||||
TotalScore = 1707827,
|
TotalScore = 1707827,
|
||||||
|
Date = DateTime.Now.AddHours(-72),
|
||||||
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
||||||
BeatmapInfo = beatmapInfo,
|
BeatmapInfo = beatmapInfo,
|
||||||
Ruleset = new OsuRuleset().RulesetInfo,
|
Ruleset = new OsuRuleset().RulesetInfo,
|
||||||
@ -380,6 +388,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
Accuracy = 0.5140,
|
Accuracy = 0.5140,
|
||||||
MaxCombo = 244,
|
MaxCombo = 244,
|
||||||
TotalScore = 1707827,
|
TotalScore = 1707827,
|
||||||
|
Date = DateTime.Now.AddMonths(-3),
|
||||||
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
||||||
BeatmapInfo = beatmapInfo,
|
BeatmapInfo = beatmapInfo,
|
||||||
Ruleset = new OsuRuleset().RulesetInfo,
|
Ruleset = new OsuRuleset().RulesetInfo,
|
||||||
@ -401,6 +410,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
Accuracy = 0.4222,
|
Accuracy = 0.4222,
|
||||||
MaxCombo = 244,
|
MaxCombo = 244,
|
||||||
TotalScore = 1707827,
|
TotalScore = 1707827,
|
||||||
|
Date = DateTime.Now.AddYears(-2),
|
||||||
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
||||||
BeatmapInfo = beatmapInfo,
|
BeatmapInfo = beatmapInfo,
|
||||||
Ruleset = new OsuRuleset().RulesetInfo,
|
Ruleset = new OsuRuleset().RulesetInfo,
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Screens;
|
using osu.Framework.Screens;
|
||||||
|
using osu.Game.Database;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
using osu.Game.Online.Multiplayer;
|
using osu.Game.Online.Multiplayer;
|
||||||
using osu.Game.Screens;
|
using osu.Game.Screens;
|
||||||
@ -37,7 +39,16 @@ namespace osu.Game.Tests.Visual
|
|||||||
public new bool IsLoaded => base.IsLoaded && MultiplayerScreen.IsLoaded;
|
public new bool IsLoaded => base.IsLoaded && MultiplayerScreen.IsLoaded;
|
||||||
|
|
||||||
[Cached(typeof(MultiplayerClient))]
|
[Cached(typeof(MultiplayerClient))]
|
||||||
public readonly TestMultiplayerClient Client;
|
public readonly TestMultiplayerClient MultiplayerClient;
|
||||||
|
|
||||||
|
[Cached(typeof(UserLookupCache))]
|
||||||
|
private readonly UserLookupCache userLookupCache = new TestUserLookupCache();
|
||||||
|
|
||||||
|
[Cached]
|
||||||
|
private readonly BeatmapLookupCache beatmapLookupCache = new BeatmapLookupCache();
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private BeatmapManager beatmapManager { get; set; }
|
||||||
|
|
||||||
private readonly OsuScreenStack screenStack;
|
private readonly OsuScreenStack screenStack;
|
||||||
private readonly TestMultiplayer multiplayerScreen;
|
private readonly TestMultiplayer multiplayerScreen;
|
||||||
@ -48,7 +59,9 @@ namespace osu.Game.Tests.Visual
|
|||||||
|
|
||||||
InternalChildren = new Drawable[]
|
InternalChildren = new Drawable[]
|
||||||
{
|
{
|
||||||
Client = new TestMultiplayerClient(RoomManager),
|
userLookupCache,
|
||||||
|
beatmapLookupCache,
|
||||||
|
MultiplayerClient = new TestMultiplayerClient(RoomManager),
|
||||||
screenStack = new OsuScreenStack
|
screenStack = new OsuScreenStack
|
||||||
{
|
{
|
||||||
Name = nameof(TestMultiplayerComponents),
|
Name = nameof(TestMultiplayerComponents),
|
||||||
@ -60,9 +73,9 @@ namespace osu.Game.Tests.Visual
|
|||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(IAPIProvider api, OsuGameBase game)
|
private void load(IAPIProvider api)
|
||||||
{
|
{
|
||||||
((DummyAPIAccess)api).HandleRequest = request => multiplayerScreen.RequestsHandler.HandleRequest(request, api.LocalUser.Value, game);
|
((DummyAPIAccess)api).HandleRequest = request => multiplayerScreen.RequestsHandler.HandleRequest(request, api.LocalUser.Value, beatmapManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool OnBackButton() => (screenStack.CurrentScreen as OsuScreen)?.OnBackButton() ?? base.OnBackButton();
|
public override bool OnBackButton() => (screenStack.CurrentScreen as OsuScreen)?.OnBackButton() ?? base.OnBackButton();
|
||||||
|
@ -0,0 +1,158 @@
|
|||||||
|
// 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.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Game.Graphics.Containers;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
using osu.Game.Overlays;
|
||||||
|
using osu.Game.Overlays.Settings.Sections;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.UserInterface
|
||||||
|
{
|
||||||
|
public class TestSceneExpandingContainer : OsuManualInputManagerTestScene
|
||||||
|
{
|
||||||
|
private TestExpandingContainer container;
|
||||||
|
private SettingsToolboxGroup toolboxGroup;
|
||||||
|
|
||||||
|
private ExpandableSlider<float, SizeSlider> slider1;
|
||||||
|
private ExpandableSlider<double> slider2;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void SetUp() => Schedule(() =>
|
||||||
|
{
|
||||||
|
Child = container = new TestExpandingContainer
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Height = 0.33f,
|
||||||
|
Child = toolboxGroup = new SettingsToolboxGroup("sliders")
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Width = 1,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
slider1 = new ExpandableSlider<float, SizeSlider>
|
||||||
|
{
|
||||||
|
Current = new BindableFloat
|
||||||
|
{
|
||||||
|
Default = 1.0f,
|
||||||
|
MinValue = 1.0f,
|
||||||
|
MaxValue = 10.0f,
|
||||||
|
Precision = 0.01f,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
slider2 = new ExpandableSlider<double>
|
||||||
|
{
|
||||||
|
Current = new BindableDouble
|
||||||
|
{
|
||||||
|
Default = 1.0,
|
||||||
|
MinValue = 1.0,
|
||||||
|
MaxValue = 10.0,
|
||||||
|
Precision = 0.01,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
slider1.Current.BindValueChanged(v =>
|
||||||
|
{
|
||||||
|
slider1.ExpandedLabelText = $"Slider One ({v.NewValue:0.##x})";
|
||||||
|
slider1.ContractedLabelText = $"S. 1. ({v.NewValue:0.##x})";
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
slider2.Current.BindValueChanged(v =>
|
||||||
|
{
|
||||||
|
slider2.ExpandedLabelText = $"Slider Two ({v.NewValue:N2})";
|
||||||
|
slider2.ContractedLabelText = $"S. 2. ({v.NewValue:N2})";
|
||||||
|
}, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestDisplay()
|
||||||
|
{
|
||||||
|
AddStep("switch to contracted", () => container.Expanded.Value = false);
|
||||||
|
AddStep("switch to expanded", () => container.Expanded.Value = true);
|
||||||
|
AddStep("set left origin", () => container.Origin = Anchor.CentreLeft);
|
||||||
|
AddStep("set centre origin", () => container.Origin = Anchor.Centre);
|
||||||
|
AddStep("set right origin", () => container.Origin = Anchor.CentreRight);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests hovering expands the container and does not contract until hover is lost.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestHoveringExpandsContainer()
|
||||||
|
{
|
||||||
|
AddAssert("ensure container contracted", () => !container.Expanded.Value);
|
||||||
|
|
||||||
|
AddStep("hover container", () => InputManager.MoveMouseTo(container));
|
||||||
|
AddAssert("container expanded", () => container.Expanded.Value);
|
||||||
|
AddAssert("controls expanded", () => slider1.Expanded.Value && slider2.Expanded.Value);
|
||||||
|
|
||||||
|
AddStep("hover away", () => InputManager.MoveMouseTo(Vector2.Zero));
|
||||||
|
AddAssert("container contracted", () => !container.Expanded.Value);
|
||||||
|
AddAssert("controls contracted", () => !slider1.Expanded.Value && !slider2.Expanded.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests expanding a container will expand underlying groups if contracted.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestExpandingContainerExpandsContractedGroup()
|
||||||
|
{
|
||||||
|
AddStep("contract group", () => toolboxGroup.Expanded.Value = false);
|
||||||
|
|
||||||
|
AddStep("expand container", () => container.Expanded.Value = true);
|
||||||
|
AddAssert("group expanded", () => toolboxGroup.Expanded.Value);
|
||||||
|
AddAssert("controls expanded", () => slider1.Expanded.Value && slider2.Expanded.Value);
|
||||||
|
|
||||||
|
AddStep("contract container", () => container.Expanded.Value = false);
|
||||||
|
AddAssert("group contracted", () => !toolboxGroup.Expanded.Value);
|
||||||
|
AddAssert("controls contracted", () => !slider1.Expanded.Value && !slider2.Expanded.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests contracting a container does not contract underlying groups if expanded by user (i.e. by setting <see cref="SettingsToolboxGroup.Expanded"/> directly).
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestContractingContainerDoesntContractUserExpandedGroup()
|
||||||
|
{
|
||||||
|
AddAssert("ensure group expanded", () => toolboxGroup.Expanded.Value);
|
||||||
|
|
||||||
|
AddStep("expand container", () => container.Expanded.Value = true);
|
||||||
|
AddAssert("group still expanded", () => toolboxGroup.Expanded.Value);
|
||||||
|
AddAssert("controls expanded", () => slider1.Expanded.Value && slider2.Expanded.Value);
|
||||||
|
|
||||||
|
AddStep("contract container", () => container.Expanded.Value = false);
|
||||||
|
AddAssert("group still expanded", () => toolboxGroup.Expanded.Value);
|
||||||
|
AddAssert("controls contracted", () => !slider1.Expanded.Value && !slider2.Expanded.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests expanding a container via <see cref="ExpandingContainer.Expanded"/> does not get contracted by losing hover.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestExpandingContainerDoesntGetContractedByHover()
|
||||||
|
{
|
||||||
|
AddStep("expand container", () => container.Expanded.Value = true);
|
||||||
|
|
||||||
|
AddStep("hover container", () => InputManager.MoveMouseTo(container));
|
||||||
|
AddAssert("container still expanded", () => container.Expanded.Value);
|
||||||
|
|
||||||
|
AddStep("hover away", () => InputManager.MoveMouseTo(Vector2.Zero));
|
||||||
|
AddAssert("container still expanded", () => container.Expanded.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestExpandingContainer : ExpandingContainer
|
||||||
|
{
|
||||||
|
public TestExpandingContainer()
|
||||||
|
: base(120, 250)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -12,7 +12,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Label="Code Analysis">
|
<PropertyGroup Label="Code Analysis">
|
||||||
<CodeAnalysisRuleSet>tests.ruleset</CodeAnalysisRuleSet>
|
<CodeAnalysisRuleSet>tests.ruleset</CodeAnalysisRuleSet>
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Label="Project References">
|
<ItemGroup Label="Project References">
|
||||||
<ProjectReference Include="..\osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj" />
|
<ProjectReference Include="..\osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj" />
|
||||||
@ -20,4 +20,4 @@
|
|||||||
<ProjectReference Include="..\osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj" />
|
<ProjectReference Include="..\osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj" />
|
||||||
<ProjectReference Include="..\osu.Game.Tournament\osu.Game.Tournament.csproj" />
|
<ProjectReference Include="..\osu.Game.Tournament\osu.Game.Tournament.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -22,6 +22,7 @@ using osu.Game.Overlays.Notifications;
|
|||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
using osu.Game.Stores;
|
using osu.Game.Stores;
|
||||||
|
using osu.Game.Utils;
|
||||||
|
|
||||||
#nullable enable
|
#nullable enable
|
||||||
|
|
||||||
@ -108,39 +109,78 @@ namespace osu.Game.Beatmaps
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Add a new difficulty to the beatmap set represented by the provided <see cref="BeatmapSetInfo"/>.
|
/// Add a new difficulty to the provided <paramref name="targetBeatmapSet"/> based on the provided <paramref name="referenceWorkingBeatmap"/>.
|
||||||
/// The new difficulty will be backed by a <see cref="BeatmapInfo"/> model
|
/// The new difficulty will be backed by a <see cref="BeatmapInfo"/> model
|
||||||
/// and represented by the returned <see cref="WorkingBeatmap"/>.
|
/// and represented by the returned <see cref="WorkingBeatmap"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual WorkingBeatmap CreateNewBlankDifficulty(BeatmapSetInfo beatmapSetInfo, RulesetInfo rulesetInfo)
|
/// <remarks>
|
||||||
|
/// Contrary to <see cref="CopyExistingDifficulty"/>, this method does not preserve hitobjects and beatmap-level settings from <paramref name="referenceWorkingBeatmap"/>.
|
||||||
|
/// The created beatmap will have zero hitobjects and will have default settings (including difficulty settings), but will preserve metadata and existing timing points.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="targetBeatmapSet">The <see cref="BeatmapSetInfo"/> to add the new difficulty to.</param>
|
||||||
|
/// <param name="referenceWorkingBeatmap">The <see cref="WorkingBeatmap"/> to use as a baseline reference when creating the new difficulty.</param>
|
||||||
|
/// <param name="rulesetInfo">The ruleset with which the new difficulty should be created.</param>
|
||||||
|
public virtual WorkingBeatmap CreateNewDifficulty(BeatmapSetInfo targetBeatmapSet, WorkingBeatmap referenceWorkingBeatmap, RulesetInfo rulesetInfo)
|
||||||
{
|
{
|
||||||
// fetch one of the existing difficulties to copy timing points and metadata from,
|
var playableBeatmap = referenceWorkingBeatmap.GetPlayableBeatmap(rulesetInfo);
|
||||||
// so that the user doesn't have to fill all of that out again.
|
|
||||||
// this silently assumes that all difficulties have the same timing points and metadata,
|
|
||||||
// but cases where this isn't true seem rather rare / pathological.
|
|
||||||
var referenceBeatmap = GetWorkingBeatmap(beatmapSetInfo.Beatmaps.First());
|
|
||||||
|
|
||||||
var newBeatmapInfo = new BeatmapInfo(rulesetInfo, new BeatmapDifficulty(), referenceBeatmap.Metadata.DeepClone());
|
var newBeatmapInfo = new BeatmapInfo(rulesetInfo, new BeatmapDifficulty(), playableBeatmap.Metadata.DeepClone())
|
||||||
|
{
|
||||||
|
DifficultyName = NamingUtils.GetNextBestName(targetBeatmapSet.Beatmaps.Select(b => b.DifficultyName), "New Difficulty")
|
||||||
|
};
|
||||||
|
var newBeatmap = new Beatmap { BeatmapInfo = newBeatmapInfo };
|
||||||
|
foreach (var timingPoint in playableBeatmap.ControlPointInfo.TimingPoints)
|
||||||
|
newBeatmap.ControlPointInfo.Add(timingPoint.Time, timingPoint.DeepClone());
|
||||||
|
|
||||||
|
return addDifficultyToSet(targetBeatmapSet, newBeatmap, referenceWorkingBeatmap.Skin);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add a copy of the provided <paramref name="referenceWorkingBeatmap"/> to the provided <paramref name="targetBeatmapSet"/>.
|
||||||
|
/// The new difficulty will be backed by a <see cref="BeatmapInfo"/> model
|
||||||
|
/// and represented by the returned <see cref="WorkingBeatmap"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Contrary to <see cref="CreateNewDifficulty"/>, this method creates a nearly-exact copy of <paramref name="referenceWorkingBeatmap"/>
|
||||||
|
/// (with the exception of a few key properties that cannot be copied under any circumstance, like difficulty name, beatmap hash, or online status).
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="targetBeatmapSet">The <see cref="BeatmapSetInfo"/> to add the copy to.</param>
|
||||||
|
/// <param name="referenceWorkingBeatmap">The <see cref="WorkingBeatmap"/> to be copied.</param>
|
||||||
|
public virtual WorkingBeatmap CopyExistingDifficulty(BeatmapSetInfo targetBeatmapSet, WorkingBeatmap referenceWorkingBeatmap)
|
||||||
|
{
|
||||||
|
var newBeatmap = referenceWorkingBeatmap.GetPlayableBeatmap(referenceWorkingBeatmap.BeatmapInfo.Ruleset).Clone();
|
||||||
|
BeatmapInfo newBeatmapInfo;
|
||||||
|
|
||||||
|
newBeatmap.BeatmapInfo = newBeatmapInfo = referenceWorkingBeatmap.BeatmapInfo.Clone();
|
||||||
|
// assign a new ID to the clone.
|
||||||
|
newBeatmapInfo.ID = Guid.NewGuid();
|
||||||
|
// add "(copy)" suffix to difficulty name, and additionally ensure that it doesn't conflict with any other potentially pre-existing copies.
|
||||||
|
newBeatmapInfo.DifficultyName = NamingUtils.GetNextBestName(
|
||||||
|
targetBeatmapSet.Beatmaps.Select(b => b.DifficultyName),
|
||||||
|
$"{newBeatmapInfo.DifficultyName} (copy)");
|
||||||
|
// clear the hash, as that's what is used to match .osu files with their corresponding realm beatmaps.
|
||||||
|
newBeatmapInfo.Hash = string.Empty;
|
||||||
|
// clear online properties.
|
||||||
|
newBeatmapInfo.OnlineID = -1;
|
||||||
|
newBeatmapInfo.Status = BeatmapOnlineStatus.None;
|
||||||
|
|
||||||
|
return addDifficultyToSet(targetBeatmapSet, newBeatmap, referenceWorkingBeatmap.Skin);
|
||||||
|
}
|
||||||
|
|
||||||
|
private WorkingBeatmap addDifficultyToSet(BeatmapSetInfo targetBeatmapSet, IBeatmap newBeatmap, ISkin beatmapSkin)
|
||||||
|
{
|
||||||
// populate circular beatmap set info <-> beatmap info references manually.
|
// populate circular beatmap set info <-> beatmap info references manually.
|
||||||
// several places like `BeatmapModelManager.Save()` or `GetWorkingBeatmap()`
|
// several places like `BeatmapModelManager.Save()` or `GetWorkingBeatmap()`
|
||||||
// rely on them being freely traversable in both directions for correct operation.
|
// rely on them being freely traversable in both directions for correct operation.
|
||||||
beatmapSetInfo.Beatmaps.Add(newBeatmapInfo);
|
targetBeatmapSet.Beatmaps.Add(newBeatmap.BeatmapInfo);
|
||||||
newBeatmapInfo.BeatmapSet = beatmapSetInfo;
|
newBeatmap.BeatmapInfo.BeatmapSet = targetBeatmapSet;
|
||||||
|
|
||||||
var newBeatmap = new Beatmap { BeatmapInfo = newBeatmapInfo };
|
beatmapModelManager.Save(newBeatmap.BeatmapInfo, newBeatmap, beatmapSkin);
|
||||||
foreach (var timingPoint in referenceBeatmap.Beatmap.ControlPointInfo.TimingPoints)
|
|
||||||
newBeatmap.ControlPointInfo.Add(timingPoint.Time, timingPoint.DeepClone());
|
|
||||||
|
|
||||||
beatmapModelManager.Save(newBeatmapInfo, newBeatmap);
|
workingBeatmapCache.Invalidate(targetBeatmapSet);
|
||||||
|
|
||||||
workingBeatmapCache.Invalidate(beatmapSetInfo);
|
|
||||||
return GetWorkingBeatmap(newBeatmap.BeatmapInfo);
|
return GetWorkingBeatmap(newBeatmap.BeatmapInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: add back support for making a copy of another difficulty
|
|
||||||
// (likely via a separate `CopyDifficulty()` method).
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Delete a beatmap difficulty.
|
/// Delete a beatmap difficulty.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -215,7 +215,8 @@ namespace osu.Game.Database
|
|||||||
.Include(s => s.Beatmaps).ThenInclude(b => b.Metadata)
|
.Include(s => s.Beatmaps).ThenInclude(b => b.Metadata)
|
||||||
.Include(s => s.Beatmaps).ThenInclude(b => b.BaseDifficulty)
|
.Include(s => s.Beatmaps).ThenInclude(b => b.BaseDifficulty)
|
||||||
.Include(s => s.Files).ThenInclude(f => f.FileInfo)
|
.Include(s => s.Files).ThenInclude(f => f.FileInfo)
|
||||||
.Include(s => s.Metadata);
|
.Include(s => s.Metadata)
|
||||||
|
.AsSplitQuery();
|
||||||
|
|
||||||
log("Beginning beatmaps migration to realm");
|
log("Beginning beatmaps migration to realm");
|
||||||
|
|
||||||
@ -344,7 +345,8 @@ namespace osu.Game.Database
|
|||||||
.Include(s => s.Ruleset)
|
.Include(s => s.Ruleset)
|
||||||
.Include(s => s.BeatmapInfo)
|
.Include(s => s.BeatmapInfo)
|
||||||
.Include(s => s.Files)
|
.Include(s => s.Files)
|
||||||
.ThenInclude(f => f.FileInfo);
|
.ThenInclude(f => f.FileInfo)
|
||||||
|
.AsSplitQuery();
|
||||||
|
|
||||||
log("Beginning scores migration to realm");
|
log("Beginning scores migration to realm");
|
||||||
|
|
||||||
@ -434,6 +436,7 @@ namespace osu.Game.Database
|
|||||||
var existingSkins = db.SkinInfo
|
var existingSkins = db.SkinInfo
|
||||||
.Include(s => s.Files)
|
.Include(s => s.Files)
|
||||||
.ThenInclude(f => f.FileInfo)
|
.ThenInclude(f => f.FileInfo)
|
||||||
|
.AsSplitQuery()
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
// previous entries in EF are removed post migration.
|
// previous entries in EF are removed post migration.
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using osu.Framework.Extensions;
|
||||||
using osu.Game.IO.Archives;
|
using osu.Game.IO.Archives;
|
||||||
using osu.Game.Stores;
|
using osu.Game.Stores;
|
||||||
using osu.Game.Utils;
|
using osu.Game.Utils;
|
||||||
@ -63,9 +64,7 @@ namespace osu.Game.Database
|
|||||||
if (!(stream is MemoryStream memoryStream))
|
if (!(stream is MemoryStream memoryStream))
|
||||||
{
|
{
|
||||||
// This isn't used in any current path. May need to reconsider for performance reasons (ie. if we don't expect the incoming stream to be copied out).
|
// This isn't used in any current path. May need to reconsider for performance reasons (ie. if we don't expect the incoming stream to be copied out).
|
||||||
byte[] buffer = new byte[stream.Length];
|
memoryStream = new MemoryStream(stream.ReadAllBytesToArray());
|
||||||
stream.Read(buffer, 0, (int)stream.Length);
|
|
||||||
memoryStream = new MemoryStream(buffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ZipUtils.IsZipArchive(memoryStream))
|
if (ZipUtils.IsZipArchive(memoryStream))
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore.Diagnostics;
|
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using osu.Framework.Logging;
|
using osu.Framework.Logging;
|
||||||
using osu.Framework.Statistics;
|
using osu.Framework.Statistics;
|
||||||
@ -12,8 +11,9 @@ using osu.Game.Configuration;
|
|||||||
using osu.Game.IO;
|
using osu.Game.IO;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
using LogLevel = Microsoft.Extensions.Logging.LogLevel;
|
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
|
using SQLitePCL;
|
||||||
|
using LogLevel = Microsoft.Extensions.Logging.LogLevel;
|
||||||
|
|
||||||
namespace osu.Game.Database
|
namespace osu.Game.Database
|
||||||
{
|
{
|
||||||
@ -40,10 +40,10 @@ namespace osu.Game.Database
|
|||||||
static OsuDbContext()
|
static OsuDbContext()
|
||||||
{
|
{
|
||||||
// required to initialise native SQLite libraries on some platforms.
|
// required to initialise native SQLite libraries on some platforms.
|
||||||
SQLitePCL.Batteries_V2.Init();
|
Batteries_V2.Init();
|
||||||
|
|
||||||
// https://github.com/aspnet/EntityFrameworkCore/issues/9994#issuecomment-508588678
|
// https://github.com/aspnet/EntityFrameworkCore/issues/9994#issuecomment-508588678
|
||||||
SQLitePCL.raw.sqlite3_config(2 /*SQLITE_CONFIG_MULTITHREAD*/);
|
raw.sqlite3_config(2 /*SQLITE_CONFIG_MULTITHREAD*/);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -116,7 +116,6 @@ namespace osu.Game.Database
|
|||||||
optionsBuilder
|
optionsBuilder
|
||||||
// this is required for the time being due to the way we are querying in places like BeatmapStore.
|
// this is required for the time being due to the way we are querying in places like BeatmapStore.
|
||||||
// if we ever move to having consumers file their own .Includes, or get eager loading support, this could be re-enabled.
|
// if we ever move to having consumers file their own .Includes, or get eager loading support, this could be re-enabled.
|
||||||
.ConfigureWarnings(warnings => warnings.Ignore(CoreEventId.IncludeIgnoredWarning))
|
|
||||||
.UseSqlite(connectionString, sqliteOptions => sqliteOptions.CommandTimeout(10))
|
.UseSqlite(connectionString, sqliteOptions => sqliteOptions.CommandTimeout(10))
|
||||||
.UseLoggerFactory(logger.Value);
|
.UseLoggerFactory(logger.Value);
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,9 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using Humanizer;
|
||||||
using osu.Framework.Localisation;
|
using osu.Framework.Localisation;
|
||||||
|
using osu.Game.Resources.Localisation.Web;
|
||||||
|
|
||||||
namespace osu.Game.Extensions
|
namespace osu.Game.Extensions
|
||||||
{
|
{
|
||||||
@ -47,5 +49,57 @@ namespace osu.Game.Extensions
|
|||||||
|
|
||||||
return new LocalisableFormattableString(timeSpan, @"mm\:ss");
|
return new LocalisableFormattableString(timeSpan, @"mm\:ss");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Formats a provided date to a short relative string version for compact display.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="time">The time to be displayed.</param>
|
||||||
|
/// <param name="lowerCutoff">A timespan denoting the time length beneath which "now" should be displayed.</param>
|
||||||
|
/// <returns>A short relative string representing the input time.</returns>
|
||||||
|
public static string ToShortRelativeTime(this DateTimeOffset time, TimeSpan lowerCutoff)
|
||||||
|
{
|
||||||
|
if (time == default)
|
||||||
|
return "-";
|
||||||
|
|
||||||
|
var now = DateTime.Now;
|
||||||
|
var difference = now - time;
|
||||||
|
|
||||||
|
// web uses momentjs's custom locales to format the date for the purposes of the scoreboard.
|
||||||
|
// this is intended to be a best-effort, more legible approximation of that.
|
||||||
|
// compare:
|
||||||
|
// * https://github.com/ppy/osu-web/blob/a8f5a68fb435cb19a4faa4c7c4bce08c4f096933/resources/assets/lib/scoreboard-time.tsx
|
||||||
|
// * https://momentjs.com/docs/#/customization/ (reference for the customisation format)
|
||||||
|
|
||||||
|
// TODO: support localisation (probably via `CommonStrings.CountHours()` etc.)
|
||||||
|
// requires pluralisable string support framework-side
|
||||||
|
|
||||||
|
if (difference < lowerCutoff)
|
||||||
|
return CommonStrings.TimeNow.ToString();
|
||||||
|
|
||||||
|
if (difference.TotalMinutes < 1)
|
||||||
|
return "sec".ToQuantity((int)difference.TotalSeconds);
|
||||||
|
if (difference.TotalHours < 1)
|
||||||
|
return "min".ToQuantity((int)difference.TotalMinutes);
|
||||||
|
if (difference.TotalDays < 1)
|
||||||
|
return "hr".ToQuantity((int)difference.TotalHours);
|
||||||
|
|
||||||
|
// this is where this gets more complicated because of how the calendar works.
|
||||||
|
// since there's no `TotalMonths` / `TotalYears`, we have to iteratively add months/years
|
||||||
|
// and test against cutoff dates to determine how many months/years to show.
|
||||||
|
|
||||||
|
if (time > now.AddMonths(-1))
|
||||||
|
return difference.TotalDays < 2 ? "1dy" : $"{(int)difference.TotalDays}dys";
|
||||||
|
|
||||||
|
for (int months = 1; months <= 11; ++months)
|
||||||
|
{
|
||||||
|
if (time > now.AddMonths(-(months + 1)))
|
||||||
|
return months == 1 ? "1mo" : $"{months}mos";
|
||||||
|
}
|
||||||
|
|
||||||
|
int years = 1;
|
||||||
|
while (time <= now.AddYears(-(years + 1)))
|
||||||
|
years += 1;
|
||||||
|
return years == 1 ? "1yr" : $"{years}yrs";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
21
osu.Game/Graphics/Containers/ExpandingButtonContainer.cs
Normal file
21
osu.Game/Graphics/Containers/ExpandingButtonContainer.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
namespace osu.Game.Graphics.Containers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An <see cref="ExpandingContainer"/> with a long hover expansion delay.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Mostly used for buttons with explanatory labels, in which the label would display after a "long hover".
|
||||||
|
/// </remarks>
|
||||||
|
public class ExpandingButtonContainer : ExpandingContainer
|
||||||
|
{
|
||||||
|
protected ExpandingButtonContainer(float contractedWidth, float expandedWidth)
|
||||||
|
: base(contractedWidth, expandedWidth)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override double HoverExpansionDelay => 400;
|
||||||
|
}
|
||||||
|
}
|
100
osu.Game/Graphics/Containers/ExpandingContainer.cs
Normal file
100
osu.Game/Graphics/Containers/ExpandingContainer.cs
Normal file
@ -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 osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Input.Events;
|
||||||
|
using osu.Framework.Threading;
|
||||||
|
|
||||||
|
namespace osu.Game.Graphics.Containers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a <see cref="Container"/> with the ability to expand/contract on hover.
|
||||||
|
/// </summary>
|
||||||
|
public class ExpandingContainer : Container, IExpandingContainer
|
||||||
|
{
|
||||||
|
private readonly float contractedWidth;
|
||||||
|
private readonly float expandedWidth;
|
||||||
|
|
||||||
|
public BindableBool Expanded { get; } = new BindableBool();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delay before the container switches to expanded state from hover.
|
||||||
|
/// </summary>
|
||||||
|
protected virtual double HoverExpansionDelay => 0;
|
||||||
|
|
||||||
|
protected override Container<Drawable> Content => FillFlow;
|
||||||
|
|
||||||
|
protected FillFlowContainer FillFlow { get; }
|
||||||
|
|
||||||
|
protected ExpandingContainer(float contractedWidth, float expandedWidth)
|
||||||
|
{
|
||||||
|
this.contractedWidth = contractedWidth;
|
||||||
|
this.expandedWidth = expandedWidth;
|
||||||
|
|
||||||
|
RelativeSizeAxes = Axes.Y;
|
||||||
|
Width = contractedWidth;
|
||||||
|
|
||||||
|
InternalChild = new OsuScrollContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
ScrollbarVisible = false,
|
||||||
|
Child = FillFlow = new FillFlowContainer
|
||||||
|
{
|
||||||
|
Origin = Anchor.CentreLeft,
|
||||||
|
Anchor = Anchor.CentreLeft,
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Direction = FillDirection.Vertical,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private ScheduledDelegate hoverExpandEvent;
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
Expanded.BindValueChanged(v =>
|
||||||
|
{
|
||||||
|
this.ResizeWidthTo(v.NewValue ? expandedWidth : contractedWidth, 500, Easing.OutQuint);
|
||||||
|
}, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool OnHover(HoverEvent e)
|
||||||
|
{
|
||||||
|
updateHoverExpansion();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool OnMouseMove(MouseMoveEvent e)
|
||||||
|
{
|
||||||
|
updateHoverExpansion();
|
||||||
|
return base.OnMouseMove(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnHoverLost(HoverLostEvent e)
|
||||||
|
{
|
||||||
|
if (hoverExpandEvent != null)
|
||||||
|
{
|
||||||
|
hoverExpandEvent?.Cancel();
|
||||||
|
hoverExpandEvent = null;
|
||||||
|
|
||||||
|
Expanded.Value = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
base.OnHoverLost(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateHoverExpansion()
|
||||||
|
{
|
||||||
|
hoverExpandEvent?.Cancel();
|
||||||
|
|
||||||
|
if (IsHovered && !Expanded.Value)
|
||||||
|
hoverExpandEvent = Scheduler.AddDelayed(() => Expanded.Value = true, HoverExpansionDelay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
19
osu.Game/Graphics/Containers/IExpandable.cs
Normal file
19
osu.Game/Graphics/Containers/IExpandable.cs
Normal file
@ -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 osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Graphics.Containers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An interface for drawables with ability to expand/contract.
|
||||||
|
/// </summary>
|
||||||
|
public interface IExpandable : IDrawable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Whether this drawable is in an expanded state.
|
||||||
|
/// </summary>
|
||||||
|
BindableBool Expanded { get; }
|
||||||
|
}
|
||||||
|
}
|
16
osu.Game/Graphics/Containers/IExpandingContainer.cs
Normal file
16
osu.Game/Graphics/Containers/IExpandingContainer.cs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
// 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.Graphics.Containers;
|
||||||
|
|
||||||
|
namespace osu.Game.Graphics.Containers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A target expanding container that should be resolved by children <see cref="IExpandable"/>s to propagate state changes.
|
||||||
|
/// </summary>
|
||||||
|
[Cached(typeof(IExpandingContainer))]
|
||||||
|
public interface IExpandingContainer : IContainer, IExpandable
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -264,32 +264,58 @@ namespace osu.Game.Graphics
|
|||||||
public readonly Color4 GrayE = Color4Extensions.FromHex(@"eee");
|
public readonly Color4 GrayE = Color4Extensions.FromHex(@"eee");
|
||||||
public readonly Color4 GrayF = Color4Extensions.FromHex(@"fff");
|
public readonly Color4 GrayF = Color4Extensions.FromHex(@"fff");
|
||||||
|
|
||||||
/// <summary>
|
#region "Basic" colour theme
|
||||||
/// Equivalent to <see cref="OverlayColourProvider.Pink"/>'s <see cref="OverlayColourProvider.Colour3"/>.
|
|
||||||
/// </summary>
|
|
||||||
public readonly Color4 Pink3 = Color4Extensions.FromHex(@"cc3378");
|
|
||||||
|
|
||||||
/// <summary>
|
// Reference: https://www.figma.com/file/VIkXMYNPMtQem2RJg9k2iQ/Asset%2FColours?node-id=1838%3A3
|
||||||
/// Equivalent to <see cref="OverlayColourProvider.Blue"/>'s <see cref="OverlayColourProvider.Colour3"/>.
|
|
||||||
/// </summary>
|
// Note that the colours in this region are also defined in `OverlayColourProvider` as `Colour{0,1,2,3,4}`.
|
||||||
|
// The difference as to which should be used where comes down to context.
|
||||||
|
// If the colour in question is supposed to always match the view in which it is displayed theme-wise, use `OverlayColourProvider`.
|
||||||
|
// If the colour usage is special and in general differs from the surrounding view in choice of hue, use the `OsuColour` constants.
|
||||||
|
|
||||||
|
public readonly Color4 Pink0 = Color4Extensions.FromHex(@"ff99c7");
|
||||||
|
public readonly Color4 Pink1 = Color4Extensions.FromHex(@"ff66ab");
|
||||||
|
public readonly Color4 Pink2 = Color4Extensions.FromHex(@"eb4791");
|
||||||
|
public readonly Color4 Pink3 = Color4Extensions.FromHex(@"cc3378");
|
||||||
|
public readonly Color4 Pink4 = Color4Extensions.FromHex(@"6b2e49");
|
||||||
|
|
||||||
|
public readonly Color4 Purple0 = Color4Extensions.FromHex(@"b299ff");
|
||||||
|
public readonly Color4 Purple1 = Color4Extensions.FromHex(@"8c66ff");
|
||||||
|
public readonly Color4 Purple2 = Color4Extensions.FromHex(@"7047eb");
|
||||||
|
public readonly Color4 Purple3 = Color4Extensions.FromHex(@"5933cc");
|
||||||
|
public readonly Color4 Purple4 = Color4Extensions.FromHex(@"3d2e6b");
|
||||||
|
|
||||||
|
public readonly Color4 Blue0 = Color4Extensions.FromHex(@"99ddff");
|
||||||
|
public readonly Color4 Blue1 = Color4Extensions.FromHex(@"66ccff");
|
||||||
|
public readonly Color4 Blue2 = Color4Extensions.FromHex(@"47b4eb");
|
||||||
public readonly Color4 Blue3 = Color4Extensions.FromHex(@"3399cc");
|
public readonly Color4 Blue3 = Color4Extensions.FromHex(@"3399cc");
|
||||||
|
public readonly Color4 Blue4 = Color4Extensions.FromHex(@"2e576b");
|
||||||
|
|
||||||
|
public readonly Color4 Green0 = Color4Extensions.FromHex(@"99ffa2");
|
||||||
|
public readonly Color4 Green1 = Color4Extensions.FromHex(@"66ff73");
|
||||||
|
public readonly Color4 Green2 = Color4Extensions.FromHex(@"47eb55");
|
||||||
|
public readonly Color4 Green3 = Color4Extensions.FromHex(@"33cc40");
|
||||||
|
public readonly Color4 Green4 = Color4Extensions.FromHex(@"2e6b33");
|
||||||
|
|
||||||
public readonly Color4 Lime0 = Color4Extensions.FromHex(@"ccff99");
|
public readonly Color4 Lime0 = Color4Extensions.FromHex(@"ccff99");
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Equivalent to <see cref="OverlayColourProvider.Lime"/>'s <see cref="OverlayColourProvider.Colour1"/>.
|
|
||||||
/// </summary>
|
|
||||||
public readonly Color4 Lime1 = Color4Extensions.FromHex(@"b2ff66");
|
public readonly Color4 Lime1 = Color4Extensions.FromHex(@"b2ff66");
|
||||||
|
public readonly Color4 Lime2 = Color4Extensions.FromHex(@"99eb47");
|
||||||
/// <summary>
|
|
||||||
/// Equivalent to <see cref="OverlayColourProvider.Lime"/>'s <see cref="OverlayColourProvider.Colour3"/>.
|
|
||||||
/// </summary>
|
|
||||||
public readonly Color4 Lime3 = Color4Extensions.FromHex(@"7fcc33");
|
public readonly Color4 Lime3 = Color4Extensions.FromHex(@"7fcc33");
|
||||||
|
public readonly Color4 Lime4 = Color4Extensions.FromHex(@"4c6b2e");
|
||||||
|
|
||||||
/// <summary>
|
public readonly Color4 Orange0 = Color4Extensions.FromHex(@"ffe699");
|
||||||
/// Equivalent to <see cref="OverlayColourProvider.Orange"/>'s <see cref="OverlayColourProvider.Colour1"/>.
|
|
||||||
/// </summary>
|
|
||||||
public readonly Color4 Orange1 = Color4Extensions.FromHex(@"ffd966");
|
public readonly Color4 Orange1 = Color4Extensions.FromHex(@"ffd966");
|
||||||
|
public readonly Color4 Orange2 = Color4Extensions.FromHex(@"ebc247");
|
||||||
|
public readonly Color4 Orange3 = Color4Extensions.FromHex(@"cca633");
|
||||||
|
public readonly Color4 Orange4 = Color4Extensions.FromHex(@"6b5c2e");
|
||||||
|
|
||||||
|
public readonly Color4 Red0 = Color4Extensions.FromHex(@"ff9b9b");
|
||||||
|
public readonly Color4 Red1 = Color4Extensions.FromHex(@"ff6666");
|
||||||
|
public readonly Color4 Red2 = Color4Extensions.FromHex(@"eb4747");
|
||||||
|
public readonly Color4 Red3 = Color4Extensions.FromHex(@"cc3333");
|
||||||
|
public readonly Color4 Red4 = Color4Extensions.FromHex(@"6b2e2e");
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
// Content Background
|
// Content Background
|
||||||
public readonly Color4 B5 = Color4Extensions.FromHex(@"222a28");
|
public readonly Color4 B5 = Color4Extensions.FromHex(@"222a28");
|
||||||
|
@ -112,6 +112,8 @@ namespace osu.Game.Graphics
|
|||||||
if (Interlocked.Decrement(ref screenShotTasks) == 0 && cursorVisibility.Value == false)
|
if (Interlocked.Decrement(ref screenShotTasks) == 0 && cursorVisibility.Value == false)
|
||||||
cursorVisibility.Value = true;
|
cursorVisibility.Value = true;
|
||||||
|
|
||||||
|
host.GetClipboard()?.SetImage(image);
|
||||||
|
|
||||||
string filename = getFilename();
|
string filename = getFilename();
|
||||||
|
|
||||||
if (filename == null) return;
|
if (filename == null) return;
|
||||||
|
126
osu.Game/Graphics/UserInterface/ExpandableSlider.cs
Normal file
126
osu.Game/Graphics/UserInterface/ExpandableSlider.cs
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
// 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 osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.UserInterface;
|
||||||
|
using osu.Framework.Localisation;
|
||||||
|
using osu.Game.Graphics.Containers;
|
||||||
|
using osu.Game.Graphics.Sprites;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Graphics.UserInterface
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An <see cref="IExpandable"/> implementation for the UI slider bar control.
|
||||||
|
/// </summary>
|
||||||
|
public class ExpandableSlider<T, TSlider> : CompositeDrawable, IExpandable, IHasCurrentValue<T>
|
||||||
|
where T : struct, IEquatable<T>, IComparable<T>, IConvertible
|
||||||
|
where TSlider : OsuSliderBar<T>, new()
|
||||||
|
{
|
||||||
|
private readonly OsuSpriteText label;
|
||||||
|
private readonly TSlider slider;
|
||||||
|
|
||||||
|
private LocalisableString contractedLabelText;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The label text to display when this slider is in a contracted state.
|
||||||
|
/// </summary>
|
||||||
|
public LocalisableString ContractedLabelText
|
||||||
|
{
|
||||||
|
get => contractedLabelText;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == contractedLabelText)
|
||||||
|
return;
|
||||||
|
|
||||||
|
contractedLabelText = value;
|
||||||
|
|
||||||
|
if (!Expanded.Value)
|
||||||
|
label.Text = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private LocalisableString expandedLabelText;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The label text to display when this slider is in an expanded state.
|
||||||
|
/// </summary>
|
||||||
|
public LocalisableString ExpandedLabelText
|
||||||
|
{
|
||||||
|
get => expandedLabelText;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == expandedLabelText)
|
||||||
|
return;
|
||||||
|
|
||||||
|
expandedLabelText = value;
|
||||||
|
|
||||||
|
if (Expanded.Value)
|
||||||
|
label.Text = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Bindable<T> Current
|
||||||
|
{
|
||||||
|
get => slider.Current;
|
||||||
|
set => slider.Current = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BindableBool Expanded { get; } = new BindableBool();
|
||||||
|
|
||||||
|
public override bool HandlePositionalInput => true;
|
||||||
|
|
||||||
|
public ExpandableSlider()
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X;
|
||||||
|
AutoSizeAxes = Axes.Y;
|
||||||
|
|
||||||
|
InternalChild = new FillFlowContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Spacing = new Vector2(0f, 10f),
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
label = new OsuSpriteText(),
|
||||||
|
slider = new TSlider
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[Resolved(canBeNull: true)]
|
||||||
|
private IExpandingContainer expandingContainer { get; set; }
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
expandingContainer?.Expanded.BindValueChanged(containerExpanded =>
|
||||||
|
{
|
||||||
|
Expanded.Value = containerExpanded.NewValue;
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
Expanded.BindValueChanged(v =>
|
||||||
|
{
|
||||||
|
label.Text = v.NewValue ? expandedLabelText : contractedLabelText;
|
||||||
|
slider.FadeTo(v.NewValue ? 1f : 0f, 500, Easing.OutQuint);
|
||||||
|
slider.BypassAutoSizeAxes = !v.NewValue ? Axes.Y : Axes.None;
|
||||||
|
}, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An <see cref="IExpandable"/> implementation for the UI slider bar control.
|
||||||
|
/// </summary>
|
||||||
|
public class ExpandableSlider<T> : ExpandableSlider<T, OsuSliderBar<T>>
|
||||||
|
where T : struct, IEquatable<T>, IComparable<T>, IConvertible
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -114,7 +114,7 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
|||||||
|
|
||||||
private class CircularBorderContainer : CircularContainer
|
private class CircularBorderContainer : CircularContainer
|
||||||
{
|
{
|
||||||
public void TransformBorderTo(SRGBColour colour)
|
public void TransformBorderTo(ColourInfo colour)
|
||||||
=> this.TransformTo(nameof(BorderColour), colour, 250, Easing.OutQuint);
|
=> this.TransformTo(nameof(BorderColour), colour, 250, Easing.OutQuint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ using System.Collections.Generic;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using osu.Framework.Extensions;
|
||||||
using osu.Framework.IO.Stores;
|
using osu.Framework.IO.Stores;
|
||||||
|
|
||||||
namespace osu.Game.IO.Archives
|
namespace osu.Game.IO.Archives
|
||||||
@ -35,14 +36,7 @@ namespace osu.Game.IO.Archives
|
|||||||
public virtual byte[] Get(string name)
|
public virtual byte[] Get(string name)
|
||||||
{
|
{
|
||||||
using (Stream input = GetStream(name))
|
using (Stream input = GetStream(name))
|
||||||
{
|
return input?.ReadAllBytesToArray();
|
||||||
if (input == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
byte[] buffer = new byte[input.Length];
|
|
||||||
input.Read(buffer);
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<byte[]> GetAsync(string name, CancellationToken cancellationToken = default)
|
public async Task<byte[]> GetAsync(string name, CancellationToken cancellationToken = default)
|
||||||
@ -52,9 +46,7 @@ namespace osu.Game.IO.Archives
|
|||||||
if (input == null)
|
if (input == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
byte[] buffer = new byte[input.Length];
|
return await input.ReadAllBytesToArrayAsync(cancellationToken).ConfigureAwait(false);
|
||||||
await input.ReadAsync(buffer, cancellationToken).ConfigureAwait(false);
|
|
||||||
return buffer;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,12 +2,13 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace osu.Game.Online.API.Requests
|
namespace osu.Game.Online.API.Requests
|
||||||
{
|
{
|
||||||
public class GetBeatmapsRequest : APIRequest<GetBeatmapsResponse>
|
public class GetBeatmapsRequest : APIRequest<GetBeatmapsResponse>
|
||||||
{
|
{
|
||||||
private readonly int[] beatmapIds;
|
public readonly IReadOnlyList<int> BeatmapIds;
|
||||||
|
|
||||||
private const int max_ids_per_request = 50;
|
private const int max_ids_per_request = 50;
|
||||||
|
|
||||||
@ -16,9 +17,9 @@ namespace osu.Game.Online.API.Requests
|
|||||||
if (beatmapIds.Length > max_ids_per_request)
|
if (beatmapIds.Length > max_ids_per_request)
|
||||||
throw new ArgumentException($"{nameof(GetBeatmapsRequest)} calls only support up to {max_ids_per_request} IDs at once");
|
throw new ArgumentException($"{nameof(GetBeatmapsRequest)} calls only support up to {max_ids_per_request} IDs at once");
|
||||||
|
|
||||||
this.beatmapIds = beatmapIds;
|
BeatmapIds = beatmapIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override string Target => "beatmaps/?ids[]=" + string.Join("&ids[]=", beatmapIds);
|
protected override string Target => "beatmaps/?ids[]=" + string.Join("&ids[]=", BeatmapIds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -112,7 +112,27 @@ namespace osu.Game.Online.API.Requests.Responses
|
|||||||
public int OnlineID { get; set; } = -1;
|
public int OnlineID { get; set; } = -1;
|
||||||
|
|
||||||
public string Name => $@"{nameof(APIRuleset)} (ID: {OnlineID})";
|
public string Name => $@"{nameof(APIRuleset)} (ID: {OnlineID})";
|
||||||
public string ShortName => nameof(APIRuleset);
|
|
||||||
|
public string ShortName
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
// TODO: this should really not exist.
|
||||||
|
switch (OnlineID)
|
||||||
|
{
|
||||||
|
case 0: return "osu";
|
||||||
|
|
||||||
|
case 1: return "taiko";
|
||||||
|
|
||||||
|
case 2: return "fruits";
|
||||||
|
|
||||||
|
case 3: return "mania";
|
||||||
|
|
||||||
|
default: throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public string InstantiationInfo => string.Empty;
|
public string InstantiationInfo => string.Empty;
|
||||||
|
|
||||||
public Ruleset CreateInstance() => throw new NotImplementedException();
|
public Ruleset CreateInstance() => throw new NotImplementedException();
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
@ -16,6 +17,7 @@ using osu.Framework.Input.Events;
|
|||||||
using osu.Framework.Localisation;
|
using osu.Framework.Localisation;
|
||||||
using osu.Framework.Platform;
|
using osu.Framework.Platform;
|
||||||
using osu.Game.Database;
|
using osu.Game.Database;
|
||||||
|
using osu.Game.Extensions;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
@ -56,7 +58,7 @@ namespace osu.Game.Online.Leaderboards
|
|||||||
|
|
||||||
public GlowingSpriteText ScoreText { get; private set; }
|
public GlowingSpriteText ScoreText { get; private set; }
|
||||||
|
|
||||||
private Container flagBadgeContainer;
|
private FillFlowContainer flagBadgeAndDateContainer;
|
||||||
private FillFlowContainer<ModIcon> modsContainer;
|
private FillFlowContainer<ModIcon> modsContainer;
|
||||||
|
|
||||||
private List<ScoreComponentLabel> statisticsLabels;
|
private List<ScoreComponentLabel> statisticsLabels;
|
||||||
@ -103,7 +105,7 @@ namespace osu.Game.Online.Leaderboards
|
|||||||
content = new Container
|
content = new Container
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Padding = new MarginPadding { Left = rank_width, },
|
Padding = new MarginPadding { Left = rank_width },
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new Container
|
new Container
|
||||||
@ -158,32 +160,41 @@ namespace osu.Game.Online.Leaderboards
|
|||||||
},
|
},
|
||||||
new FillFlowContainer
|
new FillFlowContainer
|
||||||
{
|
{
|
||||||
Origin = Anchor.BottomLeft,
|
|
||||||
Anchor = Anchor.BottomLeft,
|
Anchor = Anchor.BottomLeft,
|
||||||
|
Origin = Anchor.BottomLeft,
|
||||||
AutoSizeAxes = Axes.Both,
|
AutoSizeAxes = Axes.Both,
|
||||||
Direction = FillDirection.Horizontal,
|
Direction = FillDirection.Horizontal,
|
||||||
Spacing = new Vector2(10f, 0f),
|
Spacing = new Vector2(10f, 0f),
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
flagBadgeContainer = new Container
|
flagBadgeAndDateContainer = new FillFlowContainer
|
||||||
{
|
{
|
||||||
Origin = Anchor.BottomLeft,
|
Anchor = Anchor.CentreLeft,
|
||||||
Anchor = Anchor.BottomLeft,
|
Origin = Anchor.CentreLeft,
|
||||||
Size = new Vector2(87f, 20f),
|
RelativeSizeAxes = Axes.Y,
|
||||||
|
Direction = FillDirection.Horizontal,
|
||||||
|
Spacing = new Vector2(5f, 0f),
|
||||||
|
Width = 87f,
|
||||||
Masking = true,
|
Masking = true,
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new UpdateableFlag(user.Country)
|
new UpdateableFlag(user.Country)
|
||||||
{
|
{
|
||||||
Width = 30,
|
Anchor = Anchor.CentreLeft,
|
||||||
RelativeSizeAxes = Axes.Y,
|
Origin = Anchor.CentreLeft,
|
||||||
|
Size = new Vector2(30f, 20f),
|
||||||
|
},
|
||||||
|
new DateLabel(Score.Date)
|
||||||
|
{
|
||||||
|
Anchor = Anchor.CentreLeft,
|
||||||
|
Origin = Anchor.CentreLeft,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
new FillFlowContainer
|
new FillFlowContainer
|
||||||
{
|
{
|
||||||
Origin = Anchor.BottomLeft,
|
Origin = Anchor.CentreLeft,
|
||||||
Anchor = Anchor.BottomLeft,
|
Anchor = Anchor.CentreLeft,
|
||||||
AutoSizeAxes = Axes.Both,
|
AutoSizeAxes = Axes.Both,
|
||||||
Direction = FillDirection.Horizontal,
|
Direction = FillDirection.Horizontal,
|
||||||
Margin = new MarginPadding { Left = edge_margin },
|
Margin = new MarginPadding { Left = edge_margin },
|
||||||
@ -243,7 +254,7 @@ namespace osu.Game.Online.Leaderboards
|
|||||||
|
|
||||||
public override void Show()
|
public override void Show()
|
||||||
{
|
{
|
||||||
foreach (var d in new[] { avatar, nameLabel, ScoreText, scoreRank, flagBadgeContainer, modsContainer }.Concat(statisticsLabels))
|
foreach (var d in new[] { avatar, nameLabel, ScoreText, scoreRank, flagBadgeAndDateContainer, modsContainer }.Concat(statisticsLabels))
|
||||||
d.FadeOut();
|
d.FadeOut();
|
||||||
|
|
||||||
Alpha = 0;
|
Alpha = 0;
|
||||||
@ -270,7 +281,7 @@ namespace osu.Game.Online.Leaderboards
|
|||||||
|
|
||||||
using (BeginDelayedSequence(50))
|
using (BeginDelayedSequence(50))
|
||||||
{
|
{
|
||||||
var drawables = new Drawable[] { flagBadgeContainer, modsContainer }.Concat(statisticsLabels).ToArray();
|
var drawables = new Drawable[] { flagBadgeAndDateContainer, modsContainer }.Concat(statisticsLabels).ToArray();
|
||||||
for (int i = 0; i < drawables.Length; i++)
|
for (int i = 0; i < drawables.Length; i++)
|
||||||
drawables[i].FadeIn(100 + i * 50);
|
drawables[i].FadeIn(100 + i * 50);
|
||||||
}
|
}
|
||||||
@ -377,6 +388,17 @@ namespace osu.Game.Online.Leaderboards
|
|||||||
public LocalisableString TooltipText { get; }
|
public LocalisableString TooltipText { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class DateLabel : DrawableDate
|
||||||
|
{
|
||||||
|
public DateLabel(DateTimeOffset date)
|
||||||
|
: base(date)
|
||||||
|
{
|
||||||
|
Font = OsuFont.GetFont(size: 17, weight: FontWeight.Bold, italics: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string Format() => Date.ToShortRelativeTime(TimeSpan.FromSeconds(30));
|
||||||
|
}
|
||||||
|
|
||||||
public class LeaderboardScoreStatistic
|
public class LeaderboardScoreStatistic
|
||||||
{
|
{
|
||||||
public IconUsage Icon;
|
public IconUsage Icon;
|
||||||
|
@ -727,38 +727,17 @@ namespace osu.Game.Online.Multiplayer
|
|||||||
RoomUpdated?.Invoke();
|
RoomUpdated?.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
private PlaylistItem createPlaylistItem(MultiplayerPlaylistItem item)
|
private PlaylistItem createPlaylistItem(MultiplayerPlaylistItem item) => new PlaylistItem(new APIBeatmap { OnlineID = item.BeatmapID })
|
||||||
{
|
{
|
||||||
var ruleset = Rulesets.GetRuleset(item.RulesetID);
|
ID = item.ID,
|
||||||
|
OwnerID = item.OwnerID,
|
||||||
Debug.Assert(ruleset != null);
|
RulesetID = item.RulesetID,
|
||||||
|
Expired = item.Expired,
|
||||||
var rulesetInstance = ruleset.CreateInstance();
|
PlaylistOrder = item.PlaylistOrder,
|
||||||
|
PlayedAt = item.PlayedAt,
|
||||||
var playlistItem = new PlaylistItem
|
RequiredMods = item.RequiredMods.ToArray(),
|
||||||
{
|
AllowedMods = item.AllowedMods.ToArray()
|
||||||
ID = item.ID,
|
};
|
||||||
BeatmapID = item.BeatmapID,
|
|
||||||
OwnerID = item.OwnerID,
|
|
||||||
Ruleset = { Value = ruleset },
|
|
||||||
Expired = item.Expired,
|
|
||||||
PlaylistOrder = item.PlaylistOrder,
|
|
||||||
PlayedAt = item.PlayedAt
|
|
||||||
};
|
|
||||||
|
|
||||||
playlistItem.RequiredMods.AddRange(item.RequiredMods.Select(m => m.ToMod(rulesetInstance)));
|
|
||||||
playlistItem.AllowedMods.AddRange(item.AllowedMods.Select(m => m.ToMod(rulesetInstance)));
|
|
||||||
|
|
||||||
return playlistItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Retrieves a <see cref="APIBeatmap"/> from an online source.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="beatmapId">The beatmap ID.</param>
|
|
||||||
/// <param name="cancellationToken">A token to cancel the request.</param>
|
|
||||||
/// <returns>The <see cref="APIBeatmap"/> retrieval task.</returns>
|
|
||||||
public abstract Task<APIBeatmap> GetAPIBeatmap(int beatmapId, CancellationToken cancellationToken = default);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// For the provided user ID, update whether the user is included in <see cref="CurrentMatchPlayingUserIds"/>.
|
/// For the provided user ID, update whether the user is included in <see cref="CurrentMatchPlayingUserIds"/>.
|
||||||
|
@ -4,14 +4,13 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.SignalR.Client;
|
using Microsoft.AspNetCore.SignalR.Client;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Game.Database;
|
|
||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
using osu.Game.Online.API.Requests.Responses;
|
|
||||||
using osu.Game.Online.Rooms;
|
using osu.Game.Online.Rooms;
|
||||||
|
|
||||||
namespace osu.Game.Online.Multiplayer
|
namespace osu.Game.Online.Multiplayer
|
||||||
@ -29,9 +28,6 @@ namespace osu.Game.Online.Multiplayer
|
|||||||
|
|
||||||
private HubConnection? connection => connector?.CurrentConnection;
|
private HubConnection? connection => connector?.CurrentConnection;
|
||||||
|
|
||||||
[Resolved]
|
|
||||||
private BeatmapLookupCache beatmapLookupCache { get; set; } = null!;
|
|
||||||
|
|
||||||
public OnlineMultiplayerClient(EndpointConfiguration endpoints)
|
public OnlineMultiplayerClient(EndpointConfiguration endpoints)
|
||||||
{
|
{
|
||||||
endpoint = endpoints.MultiplayerEndpointUrl;
|
endpoint = endpoints.MultiplayerEndpointUrl;
|
||||||
@ -79,6 +75,8 @@ namespace osu.Game.Online.Multiplayer
|
|||||||
if (!IsConnected.Value)
|
if (!IsConnected.Value)
|
||||||
return Task.FromCanceled<MultiplayerRoom>(new CancellationToken(true));
|
return Task.FromCanceled<MultiplayerRoom>(new CancellationToken(true));
|
||||||
|
|
||||||
|
Debug.Assert(connection != null);
|
||||||
|
|
||||||
return connection.InvokeAsync<MultiplayerRoom>(nameof(IMultiplayerServer.JoinRoomWithPassword), roomId, password ?? string.Empty);
|
return connection.InvokeAsync<MultiplayerRoom>(nameof(IMultiplayerServer.JoinRoomWithPassword), roomId, password ?? string.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,6 +85,8 @@ namespace osu.Game.Online.Multiplayer
|
|||||||
if (!IsConnected.Value)
|
if (!IsConnected.Value)
|
||||||
return Task.FromCanceled(new CancellationToken(true));
|
return Task.FromCanceled(new CancellationToken(true));
|
||||||
|
|
||||||
|
Debug.Assert(connection != null);
|
||||||
|
|
||||||
return connection.InvokeAsync(nameof(IMultiplayerServer.LeaveRoom));
|
return connection.InvokeAsync(nameof(IMultiplayerServer.LeaveRoom));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,6 +95,8 @@ namespace osu.Game.Online.Multiplayer
|
|||||||
if (!IsConnected.Value)
|
if (!IsConnected.Value)
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
|
|
||||||
|
Debug.Assert(connection != null);
|
||||||
|
|
||||||
return connection.InvokeAsync(nameof(IMultiplayerServer.TransferHost), userId);
|
return connection.InvokeAsync(nameof(IMultiplayerServer.TransferHost), userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,6 +105,8 @@ namespace osu.Game.Online.Multiplayer
|
|||||||
if (!IsConnected.Value)
|
if (!IsConnected.Value)
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
|
|
||||||
|
Debug.Assert(connection != null);
|
||||||
|
|
||||||
return connection.InvokeAsync(nameof(IMultiplayerServer.KickUser), userId);
|
return connection.InvokeAsync(nameof(IMultiplayerServer.KickUser), userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,6 +115,8 @@ namespace osu.Game.Online.Multiplayer
|
|||||||
if (!IsConnected.Value)
|
if (!IsConnected.Value)
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
|
|
||||||
|
Debug.Assert(connection != null);
|
||||||
|
|
||||||
return connection.InvokeAsync(nameof(IMultiplayerServer.ChangeSettings), settings);
|
return connection.InvokeAsync(nameof(IMultiplayerServer.ChangeSettings), settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,6 +125,8 @@ namespace osu.Game.Online.Multiplayer
|
|||||||
if (!IsConnected.Value)
|
if (!IsConnected.Value)
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
|
|
||||||
|
Debug.Assert(connection != null);
|
||||||
|
|
||||||
return connection.InvokeAsync(nameof(IMultiplayerServer.ChangeState), newState);
|
return connection.InvokeAsync(nameof(IMultiplayerServer.ChangeState), newState);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,6 +135,8 @@ namespace osu.Game.Online.Multiplayer
|
|||||||
if (!IsConnected.Value)
|
if (!IsConnected.Value)
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
|
|
||||||
|
Debug.Assert(connection != null);
|
||||||
|
|
||||||
return connection.InvokeAsync(nameof(IMultiplayerServer.ChangeBeatmapAvailability), newBeatmapAvailability);
|
return connection.InvokeAsync(nameof(IMultiplayerServer.ChangeBeatmapAvailability), newBeatmapAvailability);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,6 +145,8 @@ namespace osu.Game.Online.Multiplayer
|
|||||||
if (!IsConnected.Value)
|
if (!IsConnected.Value)
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
|
|
||||||
|
Debug.Assert(connection != null);
|
||||||
|
|
||||||
return connection.InvokeAsync(nameof(IMultiplayerServer.ChangeUserMods), newMods);
|
return connection.InvokeAsync(nameof(IMultiplayerServer.ChangeUserMods), newMods);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,6 +155,8 @@ namespace osu.Game.Online.Multiplayer
|
|||||||
if (!IsConnected.Value)
|
if (!IsConnected.Value)
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
|
|
||||||
|
Debug.Assert(connection != null);
|
||||||
|
|
||||||
return connection.InvokeAsync(nameof(IMultiplayerServer.SendMatchRequest), request);
|
return connection.InvokeAsync(nameof(IMultiplayerServer.SendMatchRequest), request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,6 +165,8 @@ namespace osu.Game.Online.Multiplayer
|
|||||||
if (!IsConnected.Value)
|
if (!IsConnected.Value)
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
|
|
||||||
|
Debug.Assert(connection != null);
|
||||||
|
|
||||||
return connection.InvokeAsync(nameof(IMultiplayerServer.StartMatch));
|
return connection.InvokeAsync(nameof(IMultiplayerServer.StartMatch));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,6 +175,8 @@ namespace osu.Game.Online.Multiplayer
|
|||||||
if (!IsConnected.Value)
|
if (!IsConnected.Value)
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
|
|
||||||
|
Debug.Assert(connection != null);
|
||||||
|
|
||||||
return connection.InvokeAsync(nameof(IMultiplayerServer.AbortGameplay));
|
return connection.InvokeAsync(nameof(IMultiplayerServer.AbortGameplay));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,6 +185,8 @@ namespace osu.Game.Online.Multiplayer
|
|||||||
if (!IsConnected.Value)
|
if (!IsConnected.Value)
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
|
|
||||||
|
Debug.Assert(connection != null);
|
||||||
|
|
||||||
return connection.InvokeAsync(nameof(IMultiplayerServer.AddPlaylistItem), item);
|
return connection.InvokeAsync(nameof(IMultiplayerServer.AddPlaylistItem), item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,6 +195,8 @@ namespace osu.Game.Online.Multiplayer
|
|||||||
if (!IsConnected.Value)
|
if (!IsConnected.Value)
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
|
|
||||||
|
Debug.Assert(connection != null);
|
||||||
|
|
||||||
return connection.InvokeAsync(nameof(IMultiplayerServer.EditPlaylistItem), item);
|
return connection.InvokeAsync(nameof(IMultiplayerServer.EditPlaylistItem), item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,12 +205,9 @@ namespace osu.Game.Online.Multiplayer
|
|||||||
if (!IsConnected.Value)
|
if (!IsConnected.Value)
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
|
|
||||||
return connection.InvokeAsync(nameof(IMultiplayerServer.RemovePlaylistItem), playlistItemId);
|
Debug.Assert(connection != null);
|
||||||
}
|
|
||||||
|
|
||||||
public override Task<APIBeatmap> GetAPIBeatmap(int beatmapId, CancellationToken cancellationToken = default)
|
return connection.InvokeAsync(nameof(IMultiplayerServer.RemovePlaylistItem), playlistItemId);
|
||||||
{
|
|
||||||
return beatmapLookupCache.GetBeatmapAsync(beatmapId, cancellationToken);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Dispose(bool isDisposing)
|
protected override void Dispose(bool isDisposing)
|
||||||
|
@ -63,11 +63,11 @@ namespace osu.Game.Online.Rooms
|
|||||||
{
|
{
|
||||||
ID = item.ID;
|
ID = item.ID;
|
||||||
OwnerID = item.OwnerID;
|
OwnerID = item.OwnerID;
|
||||||
BeatmapID = item.BeatmapID;
|
BeatmapID = item.Beatmap.OnlineID;
|
||||||
BeatmapChecksum = item.Beatmap.Value?.MD5Hash ?? string.Empty;
|
BeatmapChecksum = item.Beatmap.MD5Hash;
|
||||||
RulesetID = item.RulesetID;
|
RulesetID = item.RulesetID;
|
||||||
RequiredMods = item.RequiredMods.Select(m => new APIMod(m)).ToArray();
|
RequiredMods = item.RequiredMods.ToArray();
|
||||||
AllowedMods = item.AllowedMods.Select(m => new APIMod(m)).ToArray();
|
AllowedMods = item.AllowedMods.ToArray();
|
||||||
Expired = item.Expired;
|
Expired = item.Expired;
|
||||||
PlaylistOrder = item.PlaylistOrder ?? 0;
|
PlaylistOrder = item.PlaylistOrder ?? 0;
|
||||||
PlayedAt = item.PlayedAt;
|
PlayedAt = item.PlayedAt;
|
||||||
|
@ -65,7 +65,11 @@ namespace osu.Game.Online.Rooms
|
|||||||
|
|
||||||
public ScoreInfo CreateScoreInfo(RulesetStore rulesets, PlaylistItem playlistItem, [NotNull] BeatmapInfo beatmap)
|
public ScoreInfo CreateScoreInfo(RulesetStore rulesets, PlaylistItem playlistItem, [NotNull] BeatmapInfo beatmap)
|
||||||
{
|
{
|
||||||
var rulesetInstance = playlistItem.Ruleset.Value.CreateInstance();
|
var ruleset = rulesets.GetRuleset(playlistItem.RulesetID);
|
||||||
|
if (ruleset == null)
|
||||||
|
throw new InvalidOperationException($"Couldn't create score with unknown ruleset: {playlistItem.RulesetID}");
|
||||||
|
|
||||||
|
var rulesetInstance = ruleset.CreateInstance();
|
||||||
|
|
||||||
var scoreInfo = new ScoreInfo
|
var scoreInfo = new ScoreInfo
|
||||||
{
|
{
|
||||||
|
@ -4,14 +4,17 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Extensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Logging;
|
using osu.Framework.Logging;
|
||||||
using osu.Framework.Threading;
|
using osu.Framework.Threading;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Database;
|
using osu.Game.Database;
|
||||||
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
using Realms;
|
using Realms;
|
||||||
|
|
||||||
namespace osu.Game.Online.Rooms
|
namespace osu.Game.Online.Rooms
|
||||||
@ -32,6 +35,9 @@ namespace osu.Game.Online.Rooms
|
|||||||
[Resolved]
|
[Resolved]
|
||||||
private RealmAccess realm { get; set; } = null!;
|
private RealmAccess realm { get; set; } = null!;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private BeatmapLookupCache beatmapLookupCache { get; set; } = null!;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The availability state of the currently selected playlist item.
|
/// The availability state of the currently selected playlist item.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -40,10 +46,9 @@ namespace osu.Game.Online.Rooms
|
|||||||
private readonly Bindable<BeatmapAvailability> availability = new Bindable<BeatmapAvailability>(BeatmapAvailability.NotDownloaded());
|
private readonly Bindable<BeatmapAvailability> availability = new Bindable<BeatmapAvailability>(BeatmapAvailability.NotDownloaded());
|
||||||
|
|
||||||
private ScheduledDelegate progressUpdate;
|
private ScheduledDelegate progressUpdate;
|
||||||
|
|
||||||
private BeatmapDownloadTracker downloadTracker;
|
private BeatmapDownloadTracker downloadTracker;
|
||||||
|
|
||||||
private IDisposable realmSubscription;
|
private IDisposable realmSubscription;
|
||||||
|
private APIBeatmap selectedBeatmap;
|
||||||
|
|
||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
||||||
{
|
{
|
||||||
@ -57,40 +62,55 @@ namespace osu.Game.Online.Rooms
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
downloadTracker?.RemoveAndDisposeImmediately();
|
downloadTracker?.RemoveAndDisposeImmediately();
|
||||||
|
selectedBeatmap = null;
|
||||||
|
|
||||||
Debug.Assert(item.NewValue.Beatmap.Value.BeatmapSet != null);
|
beatmapLookupCache.GetBeatmapAsync(item.NewValue.Beatmap.OnlineID).ContinueWith(task => Schedule(() =>
|
||||||
|
|
||||||
downloadTracker = new BeatmapDownloadTracker(item.NewValue.Beatmap.Value.BeatmapSet);
|
|
||||||
|
|
||||||
AddInternal(downloadTracker);
|
|
||||||
|
|
||||||
downloadTracker.State.BindValueChanged(_ => Scheduler.AddOnce(updateAvailability), true);
|
|
||||||
downloadTracker.Progress.BindValueChanged(_ =>
|
|
||||||
{
|
{
|
||||||
if (downloadTracker.State.Value != DownloadState.Downloading)
|
var beatmap = task.GetResultSafely();
|
||||||
return;
|
|
||||||
|
|
||||||
// incoming progress changes are going to be at a very high rate.
|
if (SelectedItem.Value?.Beatmap.OnlineID == beatmap.OnlineID)
|
||||||
// we don't want to flood the network with this, so rate limit how often we send progress updates.
|
{
|
||||||
if (progressUpdate?.Completed != false)
|
selectedBeatmap = beatmap;
|
||||||
progressUpdate = Scheduler.AddDelayed(updateAvailability, progressUpdate == null ? 0 : 500);
|
beginTracking();
|
||||||
}, true);
|
}
|
||||||
|
}), TaskContinuationOptions.OnlyOnRanToCompletion);
|
||||||
// handles changes to hash that didn't occur from the import process (ie. a user editing the beatmap in the editor, somehow).
|
|
||||||
realmSubscription?.Dispose();
|
|
||||||
realmSubscription = realm.RegisterForNotifications(r => filteredBeatmaps(), (items, changes, ___) =>
|
|
||||||
{
|
|
||||||
if (changes == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Scheduler.AddOnce(updateAvailability);
|
|
||||||
});
|
|
||||||
}, true);
|
}, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void beginTracking()
|
||||||
|
{
|
||||||
|
Debug.Assert(selectedBeatmap.BeatmapSet != null);
|
||||||
|
|
||||||
|
downloadTracker = new BeatmapDownloadTracker(selectedBeatmap.BeatmapSet);
|
||||||
|
|
||||||
|
AddInternal(downloadTracker);
|
||||||
|
|
||||||
|
downloadTracker.State.BindValueChanged(_ => Scheduler.AddOnce(updateAvailability), true);
|
||||||
|
downloadTracker.Progress.BindValueChanged(_ =>
|
||||||
|
{
|
||||||
|
if (downloadTracker.State.Value != DownloadState.Downloading)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// incoming progress changes are going to be at a very high rate.
|
||||||
|
// we don't want to flood the network with this, so rate limit how often we send progress updates.
|
||||||
|
if (progressUpdate?.Completed != false)
|
||||||
|
progressUpdate = Scheduler.AddDelayed(updateAvailability, progressUpdate == null ? 0 : 500);
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
// handles changes to hash that didn't occur from the import process (ie. a user editing the beatmap in the editor, somehow).
|
||||||
|
realmSubscription?.Dispose();
|
||||||
|
realmSubscription = realm.RegisterForNotifications(r => filteredBeatmaps(), (items, changes, ___) =>
|
||||||
|
{
|
||||||
|
if (changes == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Scheduler.AddOnce(updateAvailability);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void updateAvailability()
|
private void updateAvailability()
|
||||||
{
|
{
|
||||||
if (downloadTracker == null || SelectedItem.Value == null)
|
if (downloadTracker == null || selectedBeatmap == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch (downloadTracker.State.Value)
|
switch (downloadTracker.State.Value)
|
||||||
@ -108,12 +128,12 @@ namespace osu.Game.Online.Rooms
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case DownloadState.LocallyAvailable:
|
case DownloadState.LocallyAvailable:
|
||||||
bool hashMatches = filteredBeatmaps().Any();
|
bool available = filteredBeatmaps().Any();
|
||||||
|
|
||||||
availability.Value = hashMatches ? BeatmapAvailability.LocallyAvailable() : BeatmapAvailability.NotDownloaded();
|
availability.Value = available ? BeatmapAvailability.LocallyAvailable() : BeatmapAvailability.NotDownloaded();
|
||||||
|
|
||||||
// only display a message to the user if a download seems to have just completed.
|
// only display a message to the user if a download seems to have just completed.
|
||||||
if (!hashMatches && downloadTracker.Progress.Value == 1)
|
if (!available && downloadTracker.Progress.Value == 1)
|
||||||
Logger.Log("The imported beatmap set does not match the online version.", LoggingTarget.Runtime, LogLevel.Important);
|
Logger.Log("The imported beatmap set does not match the online version.", LoggingTarget.Runtime, LogLevel.Important);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -125,8 +145,8 @@ namespace osu.Game.Online.Rooms
|
|||||||
|
|
||||||
private IQueryable<BeatmapInfo> filteredBeatmaps()
|
private IQueryable<BeatmapInfo> filteredBeatmaps()
|
||||||
{
|
{
|
||||||
int onlineId = SelectedItem.Value.Beatmap.Value.OnlineID;
|
int onlineId = selectedBeatmap.OnlineID;
|
||||||
string checksum = SelectedItem.Value.Beatmap.Value.MD5Hash;
|
string checksum = selectedBeatmap.MD5Hash;
|
||||||
|
|
||||||
return realm.Realm
|
return realm.Realm
|
||||||
.All<BeatmapInfo>()
|
.All<BeatmapInfo>()
|
||||||
|
@ -41,6 +41,6 @@ namespace osu.Game.Online.Rooms
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static string GetTotalDuration(this BindableList<PlaylistItem> playlist) =>
|
public static string GetTotalDuration(this BindableList<PlaylistItem> playlist) =>
|
||||||
playlist.Select(p => p.Beatmap.Value.Length).Sum().Milliseconds().Humanize(minUnit: TimeUnit.Second, maxUnit: TimeUnit.Hour, precision: 2);
|
playlist.Select(p => p.Beatmap.Length).Sum().Milliseconds().Humanize(minUnit: TimeUnit.Second, maxUnit: TimeUnit.Hour, precision: 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
@ -10,11 +11,10 @@ using osu.Framework.Bindables;
|
|||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
using osu.Game.Online.API.Requests.Responses;
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
using osu.Game.Rulesets;
|
|
||||||
using osu.Game.Rulesets.Mods;
|
|
||||||
|
|
||||||
namespace osu.Game.Online.Rooms
|
namespace osu.Game.Online.Rooms
|
||||||
{
|
{
|
||||||
|
[JsonObject(MemberSerialization.OptIn)]
|
||||||
public class PlaylistItem : IEquatable<PlaylistItem>
|
public class PlaylistItem : IEquatable<PlaylistItem>
|
||||||
{
|
{
|
||||||
[JsonProperty("id")]
|
[JsonProperty("id")]
|
||||||
@ -23,9 +23,6 @@ namespace osu.Game.Online.Rooms
|
|||||||
[JsonProperty("owner_id")]
|
[JsonProperty("owner_id")]
|
||||||
public int OwnerID { get; set; }
|
public int OwnerID { get; set; }
|
||||||
|
|
||||||
[JsonProperty("beatmap_id")]
|
|
||||||
public int BeatmapID { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("ruleset_id")]
|
[JsonProperty("ruleset_id")]
|
||||||
public int RulesetID { get; set; }
|
public int RulesetID { get; set; }
|
||||||
|
|
||||||
@ -41,78 +38,50 @@ namespace osu.Game.Online.Rooms
|
|||||||
[JsonProperty("played_at")]
|
[JsonProperty("played_at")]
|
||||||
public DateTimeOffset? PlayedAt { get; set; }
|
public DateTimeOffset? PlayedAt { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("allowed_mods")]
|
||||||
|
public APIMod[] AllowedMods { get; set; } = Array.Empty<APIMod>();
|
||||||
|
|
||||||
|
[JsonProperty("required_mods")]
|
||||||
|
public APIMod[] RequiredMods { get; set; } = Array.Empty<APIMod>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Used for deserialising from the API.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("beatmap")]
|
||||||
|
private APIBeatmap apiBeatmap
|
||||||
|
{
|
||||||
|
// This getter is required/used internally by JSON.NET during deserialisation to do default-value comparisons. It is never used during serialisation (see: ShouldSerializeapiBeatmap()).
|
||||||
|
// It will always return a null value on deserialisation, which JSON.NET will handle gracefully.
|
||||||
|
get => (APIBeatmap)Beatmap;
|
||||||
|
set => Beatmap = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Used for serialising to the API.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("beatmap_id")]
|
||||||
|
private int onlineBeatmapId => Beatmap.OnlineID;
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
public IBeatmapInfo Beatmap { get; set; } = null!;
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public IBindable<bool> Valid => valid;
|
public IBindable<bool> Valid => valid;
|
||||||
|
|
||||||
private readonly Bindable<bool> valid = new BindableBool(true);
|
private readonly Bindable<bool> valid = new BindableBool(true);
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonConstructor]
|
||||||
public readonly Bindable<IBeatmapInfo> Beatmap = new Bindable<IBeatmapInfo>();
|
private PlaylistItem()
|
||||||
|
|
||||||
[JsonIgnore]
|
|
||||||
public readonly Bindable<IRulesetInfo> Ruleset = new Bindable<IRulesetInfo>();
|
|
||||||
|
|
||||||
[JsonIgnore]
|
|
||||||
public readonly BindableList<Mod> AllowedMods = new BindableList<Mod>();
|
|
||||||
|
|
||||||
[JsonIgnore]
|
|
||||||
public readonly BindableList<Mod> RequiredMods = new BindableList<Mod>();
|
|
||||||
|
|
||||||
[JsonProperty("beatmap")]
|
|
||||||
private APIBeatmap apiBeatmap { get; set; }
|
|
||||||
|
|
||||||
private APIMod[] allowedModsBacking;
|
|
||||||
|
|
||||||
[JsonProperty("allowed_mods")]
|
|
||||||
private APIMod[] allowedMods
|
|
||||||
{
|
{
|
||||||
get => AllowedMods.Select(m => new APIMod(m)).ToArray();
|
|
||||||
set => allowedModsBacking = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private APIMod[] requiredModsBacking;
|
public PlaylistItem(IBeatmapInfo beatmap)
|
||||||
|
|
||||||
[JsonProperty("required_mods")]
|
|
||||||
private APIMod[] requiredMods
|
|
||||||
{
|
{
|
||||||
get => RequiredMods.Select(m => new APIMod(m)).ToArray();
|
Beatmap = beatmap;
|
||||||
set => requiredModsBacking = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PlaylistItem()
|
|
||||||
{
|
|
||||||
Beatmap.BindValueChanged(beatmap => BeatmapID = beatmap.NewValue?.OnlineID ?? -1);
|
|
||||||
Ruleset.BindValueChanged(ruleset => RulesetID = ruleset.NewValue?.OnlineID ?? 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void MarkInvalid() => valid.Value = false;
|
public void MarkInvalid() => valid.Value = false;
|
||||||
|
|
||||||
public void MapObjects(IRulesetStore rulesets)
|
|
||||||
{
|
|
||||||
Beatmap.Value ??= apiBeatmap;
|
|
||||||
Ruleset.Value ??= rulesets.GetRuleset(RulesetID);
|
|
||||||
|
|
||||||
Debug.Assert(Ruleset.Value != null);
|
|
||||||
|
|
||||||
Ruleset rulesetInstance = Ruleset.Value.CreateInstance();
|
|
||||||
|
|
||||||
if (allowedModsBacking != null)
|
|
||||||
{
|
|
||||||
AllowedMods.Clear();
|
|
||||||
AllowedMods.AddRange(allowedModsBacking.Select(m => m.ToMod(rulesetInstance)));
|
|
||||||
|
|
||||||
allowedModsBacking = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (requiredModsBacking != null)
|
|
||||||
{
|
|
||||||
RequiredMods.Clear();
|
|
||||||
RequiredMods.AddRange(requiredModsBacking.Select(m => m.ToMod(rulesetInstance)));
|
|
||||||
|
|
||||||
requiredModsBacking = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Newtonsoft.Json implicit ShouldSerialize() methods
|
#region Newtonsoft.Json implicit ShouldSerialize() methods
|
||||||
|
|
||||||
// The properties in this region are used implicitly by Newtonsoft.Json to not serialise certain fields in some cases.
|
// The properties in this region are used implicitly by Newtonsoft.Json to not serialise certain fields in some cases.
|
||||||
@ -128,12 +97,25 @@ namespace osu.Game.Online.Rooms
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
public bool Equals(PlaylistItem other)
|
public PlaylistItem With(IBeatmapInfo beatmap) => new PlaylistItem(beatmap)
|
||||||
|
{
|
||||||
|
ID = ID,
|
||||||
|
OwnerID = OwnerID,
|
||||||
|
RulesetID = RulesetID,
|
||||||
|
Expired = Expired,
|
||||||
|
PlaylistOrder = PlaylistOrder,
|
||||||
|
PlayedAt = PlayedAt,
|
||||||
|
AllowedMods = AllowedMods,
|
||||||
|
RequiredMods = RequiredMods,
|
||||||
|
valid = { Value = Valid.Value },
|
||||||
|
};
|
||||||
|
|
||||||
|
public bool Equals(PlaylistItem? other)
|
||||||
=> ID == other?.ID
|
=> ID == other?.ID
|
||||||
&& BeatmapID == other.BeatmapID
|
&& Beatmap.OnlineID == other.Beatmap.OnlineID
|
||||||
&& RulesetID == other.RulesetID
|
&& RulesetID == other.RulesetID
|
||||||
&& Expired == other.Expired
|
&& Expired == other.Expired
|
||||||
&& allowedMods.SequenceEqual(other.allowedMods)
|
&& AllowedMods.SequenceEqual(other.AllowedMods)
|
||||||
&& requiredMods.SequenceEqual(other.requiredMods);
|
&& RequiredMods.SequenceEqual(other.RequiredMods);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -168,8 +168,7 @@ namespace osu.Game.Online.Rooms
|
|||||||
RoomID.Value = other.RoomID.Value;
|
RoomID.Value = other.RoomID.Value;
|
||||||
Name.Value = other.Name.Value;
|
Name.Value = other.Name.Value;
|
||||||
|
|
||||||
if (other.Category.Value != RoomCategory.Spotlight)
|
Category.Value = other.Category.Value;
|
||||||
Category.Value = other.Category.Value;
|
|
||||||
|
|
||||||
if (other.Host.Value != null && Host.Value?.Id != other.Host.Value.Id)
|
if (other.Host.Value != null && Host.Value?.Id != other.Host.Value.Id)
|
||||||
Host.Value = other.Host.Value;
|
Host.Value = other.Host.Value;
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#nullable enable
|
#nullable enable
|
||||||
|
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.SignalR.Client;
|
using Microsoft.AspNetCore.SignalR.Client;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
@ -51,6 +52,8 @@ namespace osu.Game.Online.Spectator
|
|||||||
if (!IsConnected.Value)
|
if (!IsConnected.Value)
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
|
|
||||||
|
Debug.Assert(connection != null);
|
||||||
|
|
||||||
return connection.SendAsync(nameof(ISpectatorServer.BeginPlaySession), state);
|
return connection.SendAsync(nameof(ISpectatorServer.BeginPlaySession), state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,6 +62,8 @@ namespace osu.Game.Online.Spectator
|
|||||||
if (!IsConnected.Value)
|
if (!IsConnected.Value)
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
|
|
||||||
|
Debug.Assert(connection != null);
|
||||||
|
|
||||||
return connection.SendAsync(nameof(ISpectatorServer.SendFrameData), data);
|
return connection.SendAsync(nameof(ISpectatorServer.SendFrameData), data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,6 +72,8 @@ namespace osu.Game.Online.Spectator
|
|||||||
if (!IsConnected.Value)
|
if (!IsConnected.Value)
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
|
|
||||||
|
Debug.Assert(connection != null);
|
||||||
|
|
||||||
return connection.SendAsync(nameof(ISpectatorServer.EndPlaySession), state);
|
return connection.SendAsync(nameof(ISpectatorServer.EndPlaySession), state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,6 +82,8 @@ namespace osu.Game.Online.Spectator
|
|||||||
if (!IsConnected.Value)
|
if (!IsConnected.Value)
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
|
|
||||||
|
Debug.Assert(connection != null);
|
||||||
|
|
||||||
return connection.SendAsync(nameof(ISpectatorServer.StartWatchingUser), userId);
|
return connection.SendAsync(nameof(ISpectatorServer.StartWatchingUser), userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,6 +92,8 @@ namespace osu.Game.Online.Spectator
|
|||||||
if (!IsConnected.Value)
|
if (!IsConnected.Value)
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
|
|
||||||
|
Debug.Assert(connection != null);
|
||||||
|
|
||||||
return connection.SendAsync(nameof(ISpectatorServer.EndWatchingUser), userId);
|
return connection.SendAsync(nameof(ISpectatorServer.EndWatchingUser), userId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Resources.Localisation.Web;
|
using osu.Game.Resources.Localisation.Web;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
|
||||||
@ -33,7 +35,10 @@ namespace osu.Game.Overlays.BeatmapListing
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Color4 GetStateColour() => OverlayColourProvider.Orange.Colour1;
|
[Resolved]
|
||||||
|
private OsuColour colours { get; set; }
|
||||||
|
|
||||||
|
protected override Color4 GetStateColour() => colours.Orange1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,14 @@ namespace osu.Game.Overlays.BeatmapListing
|
|||||||
});
|
});
|
||||||
|
|
||||||
Enabled.Value = true;
|
Enabled.Value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
updateState();
|
updateState();
|
||||||
|
FinishTransforms(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnHover(HoverEvent e)
|
protected override bool OnHover(HoverEvent e)
|
||||||
|
@ -38,7 +38,7 @@ namespace osu.Game.Overlays.BeatmapSet
|
|||||||
Margin = new MarginPadding { Horizontal = 10f, Vertical = 2f },
|
Margin = new MarginPadding { Horizontal = 10f, Vertical = 2f },
|
||||||
Text = BeatmapsetsStrings.NsfwBadgeLabel.ToUpper(),
|
Text = BeatmapsetsStrings.NsfwBadgeLabel.ToUpper(),
|
||||||
Font = OsuFont.GetFont(size: 10, weight: FontWeight.SemiBold),
|
Font = OsuFont.GetFont(size: 10, weight: FontWeight.SemiBold),
|
||||||
Colour = OverlayColourProvider.Orange.Colour2,
|
Colour = colours.Orange2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -38,7 +38,7 @@ namespace osu.Game.Overlays.BeatmapSet
|
|||||||
Margin = new MarginPadding { Horizontal = 10f, Vertical = 2f },
|
Margin = new MarginPadding { Horizontal = 10f, Vertical = 2f },
|
||||||
Text = BeatmapsetsStrings.FeaturedArtistBadgeLabel.ToUpper(),
|
Text = BeatmapsetsStrings.FeaturedArtistBadgeLabel.ToUpper(),
|
||||||
Font = OsuFont.GetFont(size: 10, weight: FontWeight.SemiBold),
|
Font = OsuFont.GetFont(size: 10, weight: FontWeight.SemiBold),
|
||||||
Colour = OverlayColourProvider.Blue.Colour1,
|
Colour = colours.Blue1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -2,9 +2,8 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using Humanizer;
|
using osu.Game.Extensions;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Resources.Localisation.Web;
|
|
||||||
|
|
||||||
namespace osu.Game.Overlays.BeatmapSet.Scores
|
namespace osu.Game.Overlays.BeatmapSet.Scores
|
||||||
{
|
{
|
||||||
@ -16,41 +15,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected override string Format()
|
protected override string Format()
|
||||||
{
|
=> Date.ToShortRelativeTime(TimeSpan.FromHours(1));
|
||||||
var now = DateTime.Now;
|
|
||||||
var difference = now - Date;
|
|
||||||
|
|
||||||
// web uses momentjs's custom locales to format the date for the purposes of the scoreboard.
|
|
||||||
// this is intended to be a best-effort, more legible approximation of that.
|
|
||||||
// compare:
|
|
||||||
// * https://github.com/ppy/osu-web/blob/a8f5a68fb435cb19a4faa4c7c4bce08c4f096933/resources/assets/lib/scoreboard-time.tsx
|
|
||||||
// * https://momentjs.com/docs/#/customization/ (reference for the customisation format)
|
|
||||||
|
|
||||||
// TODO: support localisation (probably via `CommonStrings.CountHours()` etc.)
|
|
||||||
// requires pluralisable string support framework-side
|
|
||||||
|
|
||||||
if (difference.TotalHours < 1)
|
|
||||||
return CommonStrings.TimeNow.ToString();
|
|
||||||
if (difference.TotalDays < 1)
|
|
||||||
return "hr".ToQuantity((int)difference.TotalHours);
|
|
||||||
|
|
||||||
// this is where this gets more complicated because of how the calendar works.
|
|
||||||
// since there's no `TotalMonths` / `TotalYears`, we have to iteratively add months/years
|
|
||||||
// and test against cutoff dates to determine how many months/years to show.
|
|
||||||
|
|
||||||
if (Date > now.AddMonths(-1))
|
|
||||||
return difference.TotalDays < 2 ? "1dy" : $"{(int)difference.TotalDays}dys";
|
|
||||||
|
|
||||||
for (int months = 1; months <= 11; ++months)
|
|
||||||
{
|
|
||||||
if (Date > now.AddMonths(-(months + 1)))
|
|
||||||
return months == 1 ? "1mo" : $"{months}mos";
|
|
||||||
}
|
|
||||||
|
|
||||||
int years = 1;
|
|
||||||
while (Date <= now.AddYears(-(years + 1)))
|
|
||||||
years += 1;
|
|
||||||
return years == 1 ? "1yr" : $"{years}yrs";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,141 +0,0 @@
|
|||||||
// 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 osu.Framework;
|
|
||||||
using osu.Framework.Graphics;
|
|
||||||
using osu.Framework.Graphics.Containers;
|
|
||||||
using osu.Framework.Input.Events;
|
|
||||||
using osu.Framework.Testing;
|
|
||||||
using osu.Framework.Threading;
|
|
||||||
using osu.Game.Graphics.Containers;
|
|
||||||
using osu.Game.Graphics.UserInterface;
|
|
||||||
using osuTK;
|
|
||||||
|
|
||||||
namespace osu.Game.Overlays
|
|
||||||
{
|
|
||||||
public abstract class ExpandingButtonContainer : Container, IStateful<ExpandedState>
|
|
||||||
{
|
|
||||||
private readonly float contractedWidth;
|
|
||||||
private readonly float expandedWidth;
|
|
||||||
|
|
||||||
public event Action<ExpandedState> StateChanged;
|
|
||||||
|
|
||||||
protected override Container<Drawable> Content => FillFlow;
|
|
||||||
|
|
||||||
protected FillFlowContainer FillFlow { get; }
|
|
||||||
|
|
||||||
protected ExpandingButtonContainer(float contractedWidth, float expandedWidth)
|
|
||||||
{
|
|
||||||
this.contractedWidth = contractedWidth;
|
|
||||||
this.expandedWidth = expandedWidth;
|
|
||||||
|
|
||||||
RelativeSizeAxes = Axes.Y;
|
|
||||||
Width = contractedWidth;
|
|
||||||
|
|
||||||
InternalChildren = new Drawable[]
|
|
||||||
{
|
|
||||||
new SidebarScrollContainer
|
|
||||||
{
|
|
||||||
Children = new[]
|
|
||||||
{
|
|
||||||
FillFlow = new FillFlowContainer
|
|
||||||
{
|
|
||||||
Origin = Anchor.CentreLeft,
|
|
||||||
Anchor = Anchor.CentreLeft,
|
|
||||||
AutoSizeAxes = Axes.Y,
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
Direction = FillDirection.Vertical,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private ScheduledDelegate expandEvent;
|
|
||||||
private ExpandedState state;
|
|
||||||
|
|
||||||
protected override bool OnHover(HoverEvent e)
|
|
||||||
{
|
|
||||||
queueExpandIfHovering();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnHoverLost(HoverLostEvent e)
|
|
||||||
{
|
|
||||||
expandEvent?.Cancel();
|
|
||||||
hoveredButton = null;
|
|
||||||
State = ExpandedState.Contracted;
|
|
||||||
|
|
||||||
base.OnHoverLost(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool OnMouseMove(MouseMoveEvent e)
|
|
||||||
{
|
|
||||||
queueExpandIfHovering();
|
|
||||||
return base.OnMouseMove(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
private class SidebarScrollContainer : OsuScrollContainer
|
|
||||||
{
|
|
||||||
public SidebarScrollContainer()
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both;
|
|
||||||
ScrollbarVisible = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ExpandedState State
|
|
||||||
{
|
|
||||||
get => state;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
expandEvent?.Cancel();
|
|
||||||
|
|
||||||
if (state == value) return;
|
|
||||||
|
|
||||||
state = value;
|
|
||||||
|
|
||||||
switch (state)
|
|
||||||
{
|
|
||||||
default:
|
|
||||||
this.ResizeTo(new Vector2(contractedWidth, Height), 500, Easing.OutQuint);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ExpandedState.Expanded:
|
|
||||||
this.ResizeTo(new Vector2(expandedWidth, Height), 500, Easing.OutQuint);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
StateChanged?.Invoke(State);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Drawable hoveredButton;
|
|
||||||
|
|
||||||
private void queueExpandIfHovering()
|
|
||||||
{
|
|
||||||
// if the same button is hovered, let the scheduled expand play out..
|
|
||||||
if (hoveredButton?.IsHovered == true)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// ..otherwise check whether a new button is hovered, and if so, queue a new hover operation.
|
|
||||||
|
|
||||||
// usually we wouldn't use ChildrenOfType in implementations, but this is the simplest way
|
|
||||||
// to handle cases like the editor where the buttons may be nested within a child hierarchy.
|
|
||||||
hoveredButton = FillFlow.ChildrenOfType<OsuButton>().FirstOrDefault(c => c.IsHovered);
|
|
||||||
|
|
||||||
expandEvent?.Cancel();
|
|
||||||
|
|
||||||
if (hoveredButton?.IsHovered == true && State != ExpandedState.Expanded)
|
|
||||||
expandEvent = Scheduler.AddDelayed(() => State = ExpandedState.Expanded, 750);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum ExpandedState
|
|
||||||
{
|
|
||||||
Contracted,
|
|
||||||
Expanded,
|
|
||||||
}
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user