Compare commits
116 Commits
9f779dac03
...
old-testin
| Author | SHA1 | Date | |
|---|---|---|---|
| 17d56f8db0 | |||
| 9637ea1df7 | |||
| 0940d61f7e | |||
| e6a6352a9c | |||
|
|
734c6f933d | ||
|
|
ac213c90cb | ||
|
|
74ca87c252 | ||
|
|
032912e62b | ||
|
|
1e79c56240 | ||
| 86f0159e65 | |||
| ae5a64ba81 | |||
|
|
82256ae2de | ||
|
|
1142be45ec | ||
|
|
dcb6d71287 | ||
|
|
881a35b382 | ||
|
|
89d8b402af | ||
|
|
1d351002df | ||
| e3a7ae30cd | |||
| b6f845d99c | |||
|
|
2606f3a0b5 | ||
|
|
1c463aa060 | ||
|
|
7853abe8aa | ||
|
|
1aff418981 | ||
|
|
62e92bb242 | ||
|
|
79151ae5b4 | ||
| a1d6bda63e | |||
| 547d22a4b5 | |||
|
|
c17db2cdd0 | ||
|
|
bbdd70c843 | ||
|
|
4250a54245 | ||
|
|
40fdb8662e | ||
|
|
6ce8b0a4bc | ||
|
|
b30047def6 | ||
|
|
0ffb86262f | ||
|
|
f71eb4b980 | ||
|
|
1faf02e860 | ||
|
|
d700375e55 | ||
|
|
095a67c24e | ||
|
|
86054497d0 | ||
|
|
c4f7dee82b | ||
|
|
22825f6509 | ||
|
|
691e8bcd05 | ||
|
|
e68bab4f4b | ||
|
|
9430a62af4 | ||
| b4c530ac04 | |||
| 5af05d2479 | |||
| 43ab18ffea | |||
| 9f59259a40 | |||
| 82b3015fcc | |||
| 68f92ab57c | |||
| d76d4d9a35 | |||
|
|
bb7417c099 | ||
|
|
066e093987 | ||
|
|
56e0c3e65d | ||
|
|
89d7726903 | ||
|
|
36f1bfef07 | ||
|
|
118f07878a | ||
|
|
e144968893 | ||
|
|
d2ffea41c6 | ||
|
|
a8be9b1381 | ||
|
|
bdac75e542 | ||
|
|
5c2df50714 | ||
|
|
887d280bfa | ||
|
|
42b184f167 | ||
|
|
27737bd4e9 | ||
|
|
84db289779 | ||
|
|
4c0522b795 | ||
|
|
8bb885a0dc | ||
|
|
0b06acb29d | ||
|
|
b129837e57 | ||
|
|
07ea9fe2a4 | ||
|
|
3e221c7f61 | ||
|
|
7106a6a5e5 | ||
|
|
eaf2721f5b | ||
| 490a6fd724 | |||
|
|
59a27dad3d | ||
|
|
f73307876e | ||
|
|
4e4aa44a02 | ||
|
|
d6cd748d2a | ||
| 237e1828f8 | |||
| 3413f722f7 | |||
|
|
c23d6b7fd1 | ||
|
|
582ff999aa | ||
|
|
a6c001244f | ||
|
|
a96b024ac5 | ||
|
|
1c10acba76 | ||
|
|
4ae4c700ae | ||
|
|
2be50d917a | ||
|
|
35fdc6f8b9 | ||
|
|
d04029bcc7 | ||
|
|
107098314a | ||
|
|
d1d76a76ba | ||
|
|
2a7e71d7fd | ||
|
|
0b4f96efc8 | ||
|
|
78c6973298 | ||
|
|
d8d7c80832 | ||
|
|
ae33690632 | ||
|
|
9e2ea63e70 | ||
|
|
79bfe7880a | ||
|
|
80fbcd5fbd | ||
|
|
9c2319b989 | ||
|
|
a040143825 | ||
|
|
1867aad1a6 | ||
|
|
b1bc5cae87 | ||
|
|
038bf3fdda | ||
|
|
61c3aad537 | ||
|
|
3aad0868af | ||
|
|
973c4c8319 | ||
|
|
ac21f8b960 | ||
| e78c8fa03d | |||
|
|
0b3b6468a5 | ||
|
|
7d1c54f045 | ||
|
|
fd504e5641 | ||
|
|
93ed0483b6 | ||
|
|
4dd0672aa5 | ||
|
|
66eff14d2b |
2
.github/workflows/ci.yml
vendored
@@ -39,7 +39,7 @@ jobs:
|
||||
key: inspectcode-${{ hashFiles('.config/dotnet-tools.json', '.github/workflows/ci.yml', 'osu.sln*', 'osu*.slnf', '.editorconfig', '.globalconfig', 'CodeAnalysis/*', '**/*.csproj', '**/*.props') }}
|
||||
|
||||
- name: Dotnet code style
|
||||
run: dotnet build -c Debug -warnaserror osu.Desktop.slnf -p:EnforceCodeStyleInBuild=true
|
||||
run: dotnet build -c Debug -warnaserror osu.Desktop.slnf
|
||||
|
||||
- name: CodeFileSanity
|
||||
run: |
|
||||
|
||||
4
.github/workflows/sentry-release.yml
vendored
@@ -21,8 +21,8 @@ jobs:
|
||||
uses: getsentry/action-release@v1
|
||||
env:
|
||||
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||
SENTRY_ORG: ppy
|
||||
SENTRY_PROJECT: osu
|
||||
SENTRY_ORG: jvnkosu
|
||||
SENTRY_PROJECT: client
|
||||
SENTRY_URL: https://satellite.jvnko.boats/
|
||||
with:
|
||||
environment: production
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<PackageType>Template</PackageType>
|
||||
<PackageId>ppy.osu.Game.Templates</PackageId>
|
||||
<PackageId>jvnkosu.Client.Templates</PackageId>
|
||||
<Title>osu! templates</Title>
|
||||
<Authors>ppy Pty Ltd</Authors>
|
||||
<PackageLicenseUrl>https://github.com/ppy/osu/blob/master/LICENCE</PackageLicenseUrl>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2025.1205.1" />
|
||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2025.1209.0" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<!-- Fody does not handle Android build well, and warns when unchanged.
|
||||
|
||||
@@ -148,7 +148,13 @@ namespace osu.Desktop
|
||||
|
||||
var iconStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(GetType(), "lazer.ico");
|
||||
if (iconStream != null)
|
||||
host.Window.SetIconFromStream(iconStream);
|
||||
try
|
||||
{
|
||||
host.Window.SetIconFromStream(iconStream);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
host.Window.Title = Name;
|
||||
}
|
||||
|
||||
@@ -53,8 +53,8 @@ namespace osu.Desktop.Windows
|
||||
|
||||
private static readonly UriAssociation[] uri_associations =
|
||||
{
|
||||
new UriAssociation(@"osu", WindowsAssociationManagerStrings.OsuProtocol, Icons.Lazer),
|
||||
new UriAssociation(@"osump", WindowsAssociationManagerStrings.OsuMultiplayer, Icons.Lazer),
|
||||
new UriAssociation(@"jvnkosu", WindowsAssociationManagerStrings.OsuProtocol, Icons.Lazer),
|
||||
new UriAssociation(@"jvnkosump", WindowsAssociationManagerStrings.OsuMultiplayer, Icons.Lazer),
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Skinning;
|
||||
using osu.Game.Tests.Visual;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
public partial class TestSceneGameplayCursorSizeChange : PlayerTestScene
|
||||
{
|
||||
private const float initial_cursor_size = 1f;
|
||||
protected override Ruleset CreatePlayerRuleset() => new OsuRuleset();
|
||||
|
||||
[Resolved]
|
||||
private SkinManager? skins { get; set; }
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
if (skins != null) skins.CurrentSkinInfo.Value = skins.DefaultClassicSkin.SkinInfo;
|
||||
}
|
||||
|
||||
[SetUpSteps]
|
||||
public override void SetUpSteps()
|
||||
{
|
||||
base.SetUpSteps();
|
||||
|
||||
AddStep("Set gameplay cursor size: 1", () => LocalConfig.SetValue(OsuSetting.GameplayCursorSize, initial_cursor_size));
|
||||
AddStep("resume player", () => Player.GameplayClockContainer.Start());
|
||||
AddUntilStep("clock running", () => Player.GameplayClockContainer.IsRunning);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestPausedChangeCursorSize()
|
||||
{
|
||||
AddStep("move cursor to center", () => InputManager.MoveMouseTo(Player.ScreenSpaceDrawQuad.Centre));
|
||||
AddStep("move cursor to top left", () => InputManager.MoveMouseTo(Player.ScreenSpaceDrawQuad.TopLeft));
|
||||
AddStep("move cursor to center", () => InputManager.MoveMouseTo(Player.ScreenSpaceDrawQuad.Centre));
|
||||
AddStep("move cursor to top right", () => InputManager.MoveMouseTo(Player.ScreenSpaceDrawQuad.TopRight));
|
||||
AddStep("press escape", () => InputManager.Key(Key.Escape));
|
||||
|
||||
AddSliderStep("cursor size", 0.1f, 2f, 1f, v => LocalConfig.SetValue(OsuSetting.GameplayCursorSize, v));
|
||||
}
|
||||
|
||||
protected override TestPlayer CreatePlayer(Ruleset ruleset) => new TestPlayer(true, false);
|
||||
}
|
||||
}
|
||||
@@ -1,16 +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 osu.Framework.Audio;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Overlays.Settings;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
public class OsuModRateAdjustConcrete : ModRateAdjustConcrete
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -232,10 +232,7 @@ namespace osu.Game.Rulesets.Osu
|
||||
|
||||
case ModType.Special:
|
||||
#if DEBUG
|
||||
return new Mod[]
|
||||
{
|
||||
new OsuModRateAdjustConcrete(),
|
||||
};
|
||||
return Array.Empty<Mod>();
|
||||
#endif
|
||||
|
||||
default:
|
||||
@@ -257,7 +254,11 @@ namespace osu.Game.Rulesets.Osu
|
||||
|
||||
public override string ShortName => SHORT_NAME;
|
||||
|
||||
#if !DEBUG
|
||||
public override string PlayingVerb => "Clicking circles";
|
||||
#else
|
||||
public override string PlayingVerb => "Debugging circles";
|
||||
#endif
|
||||
|
||||
public override RulesetSettingsSubsection CreateSettings() => new OsuSettingsSubsection(this);
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ namespace osu.Game.Rulesets.Taiko.Mods
|
||||
public override ModType Type => ModType.Conversion;
|
||||
public override double ScoreMultiplier => 1;
|
||||
public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModRandom)).ToArray();
|
||||
public override bool Ranked => true;
|
||||
|
||||
public void ApplyToBeatmap(IBeatmap beatmap)
|
||||
{
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace osu.Game.Tests.Chat
|
||||
public void OneTimeSetUp()
|
||||
{
|
||||
originalWebsiteRootUrl = MessageFormatter.WebsiteRootUrl;
|
||||
MessageFormatter.WebsiteRootUrl = "dev.ppy.sh";
|
||||
MessageFormatter.WebsiteRootUrl = "osu.jvnko.boats";
|
||||
}
|
||||
|
||||
[OneTimeTearDown]
|
||||
@@ -47,11 +47,11 @@ namespace osu.Game.Tests.Chat
|
||||
[Test]
|
||||
public void TestSupportedProtocolLinkParsing()
|
||||
{
|
||||
Message result = MessageFormatter.FormatMessage(new Message { Content = "forgotspacehttps://dev.ppy.sh joinmyosump://12345 jointheosu://chan/#english" });
|
||||
Message result = MessageFormatter.FormatMessage(new Message { Content = "forgotspacehttps://osu.jvnko.boats joinmyjvnkosump://12345 jointhejvnkosu://chan/#english" });
|
||||
|
||||
Assert.AreEqual("https://dev.ppy.sh", result.Links[0].Url);
|
||||
Assert.AreEqual("osump://12345", result.Links[1].Url);
|
||||
Assert.AreEqual("osu://chan/#english", result.Links[2].Url);
|
||||
Assert.AreEqual("https://osu.jvnko.boats", result.Links[0].Url);
|
||||
Assert.AreEqual("jvnkosump://12345", result.Links[1].Url);
|
||||
Assert.AreEqual("jvnkosu://chan/#english", result.Links[2].Url);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -66,15 +66,15 @@ namespace osu.Game.Tests.Chat
|
||||
Assert.AreEqual(36, result.Links[0].Length);
|
||||
}
|
||||
|
||||
[TestCase(LinkAction.OpenBeatmap, "456", "https://dev.ppy.sh/beatmapsets/123#osu/456")]
|
||||
[TestCase(LinkAction.OpenBeatmap, "456", "https://dev.ppy.sh/beatmapsets/123#osu/456?whatever")]
|
||||
[TestCase(LinkAction.OpenBeatmap, "456", "https://dev.ppy.sh/beatmapsets/123/456")]
|
||||
[TestCase(LinkAction.External, "https://dev.ppy.sh/beatmapsets/abc/def", "https://dev.ppy.sh/beatmapsets/abc/def")]
|
||||
[TestCase(LinkAction.OpenBeatmapSet, "123", "https://dev.ppy.sh/beatmapsets/123")]
|
||||
[TestCase(LinkAction.OpenBeatmapSet, "123", "https://dev.ppy.sh/beatmapsets/123/whatever")]
|
||||
[TestCase(LinkAction.External, "https://dev.ppy.sh/beatmapsets/abc", "https://dev.ppy.sh/beatmapsets/abc")]
|
||||
[TestCase(LinkAction.External, "https://dev.ppy.sh/beatmapsets/discussions", "https://dev.ppy.sh/beatmapsets/discussions")]
|
||||
[TestCase(LinkAction.External, "https://dev.ppy.sh/beatmapsets/discussions/123", "https://dev.ppy.sh/beatmapsets/discussions/123")]
|
||||
[TestCase(LinkAction.OpenBeatmap, "456", "https://osu.jvnko.boats/beatmapsets/123#osu/456")]
|
||||
[TestCase(LinkAction.OpenBeatmap, "456", "https://osu.jvnko.boats/beatmapsets/123#osu/456?whatever")]
|
||||
[TestCase(LinkAction.OpenBeatmap, "456", "https://osu.jvnko.boats/beatmapsets/123/456")]
|
||||
[TestCase(LinkAction.External, "https://osu.jvnko.boats/beatmapsets/abc/def", "https://osu.jvnko.boats/beatmapsets/abc/def")]
|
||||
[TestCase(LinkAction.OpenBeatmapSet, "123", "https://osu.jvnko.boats/beatmapsets/123")]
|
||||
[TestCase(LinkAction.OpenBeatmapSet, "123", "https://osu.jvnko.boats/beatmapsets/123/whatever")]
|
||||
[TestCase(LinkAction.External, "https://osu.jvnko.boats/beatmapsets/abc", "https://osu.jvnko.boats/beatmapsets/abc")]
|
||||
[TestCase(LinkAction.External, "https://osu.jvnko.boats/beatmapsets/discussions", "https://osu.jvnko.boats/beatmapsets/discussions")]
|
||||
[TestCase(LinkAction.External, "https://osu.jvnko.boats/beatmapsets/discussions/123", "https://osu.jvnko.boats/beatmapsets/discussions/123")]
|
||||
public void TestBeatmapLinks(LinkAction expectedAction, string expectedArg, string link)
|
||||
{
|
||||
Message result = MessageFormatter.FormatMessage(new Message { Content = link });
|
||||
@@ -150,7 +150,7 @@ namespace osu.Game.Tests.Chat
|
||||
|
||||
Assert.AreEqual("This is a Wiki Link.", result.DisplayContent);
|
||||
Assert.AreEqual(1, result.Links.Count);
|
||||
Assert.AreEqual("https://dev.ppy.sh/wiki/Wiki Link", result.Links[0].Url);
|
||||
Assert.AreEqual("https://osu.jvnko.boats/wiki/Wiki Link", result.Links[0].Url);
|
||||
Assert.AreEqual(10, result.Links[0].Index);
|
||||
Assert.AreEqual(9, result.Links[0].Length);
|
||||
}
|
||||
@@ -163,15 +163,15 @@ namespace osu.Game.Tests.Chat
|
||||
Assert.AreEqual("This is a Wiki Link Wiki:LinkWiki.Link.", result.DisplayContent);
|
||||
Assert.AreEqual(3, result.Links.Count);
|
||||
|
||||
Assert.AreEqual("https://dev.ppy.sh/wiki/Wiki Link", result.Links[0].Url);
|
||||
Assert.AreEqual("https://osu.jvnko.boats/wiki/Wiki Link", result.Links[0].Url);
|
||||
Assert.AreEqual(10, result.Links[0].Index);
|
||||
Assert.AreEqual(9, result.Links[0].Length);
|
||||
|
||||
Assert.AreEqual("https://dev.ppy.sh/wiki/Wiki:Link", result.Links[1].Url);
|
||||
Assert.AreEqual("https://osu.jvnko.boats/wiki/Wiki:Link", result.Links[1].Url);
|
||||
Assert.AreEqual(20, result.Links[1].Index);
|
||||
Assert.AreEqual(9, result.Links[1].Length);
|
||||
|
||||
Assert.AreEqual("https://dev.ppy.sh/wiki/Wiki.Link", result.Links[2].Url);
|
||||
Assert.AreEqual("https://osu.jvnko.boats/wiki/Wiki.Link", result.Links[2].Url);
|
||||
Assert.AreEqual(29, result.Links[2].Index);
|
||||
Assert.AreEqual(9, result.Links[2].Length);
|
||||
}
|
||||
@@ -452,7 +452,7 @@ namespace osu.Game.Tests.Chat
|
||||
Assert.AreEqual(1, result.Links.Count);
|
||||
Assert.AreEqual($"{OsuGameBase.OSU_PROTOCOL}chan/#english", result.Links[0].Url);
|
||||
Assert.AreEqual(26, result.Links[0].Index);
|
||||
Assert.AreEqual(19, result.Links[0].Length);
|
||||
Assert.AreEqual(23, result.Links[0].Length);
|
||||
|
||||
result = MessageFormatter.FormatMessage(new Message { Content = $"This is a [custom protocol]({OsuGameBase.OSU_PROTOCOL}chan/#english)." });
|
||||
|
||||
@@ -467,13 +467,13 @@ namespace osu.Game.Tests.Chat
|
||||
[Test]
|
||||
public void TestOsuMpProtocol()
|
||||
{
|
||||
Message result = MessageFormatter.FormatMessage(new Message { Content = "Join my multiplayer game osump://12346." });
|
||||
Message result = MessageFormatter.FormatMessage(new Message { Content = "Join my multiplayer game jvnkosump://12346." });
|
||||
|
||||
Assert.AreEqual(result.Content, result.DisplayContent);
|
||||
Assert.AreEqual(1, result.Links.Count);
|
||||
Assert.AreEqual("osump://12346", result.Links[0].Url);
|
||||
Assert.AreEqual("jvnkosump://12346", result.Links[0].Url);
|
||||
Assert.AreEqual(25, result.Links[0].Index);
|
||||
Assert.AreEqual(13, result.Links[0].Length);
|
||||
Assert.AreEqual(17, result.Links[0].Length);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -499,7 +499,7 @@ namespace osu.Game.Tests.Chat
|
||||
Assert.AreEqual("This is a simple test with some [traps] and wiki links. Don't forget to visit https://osu.ppy.sh now![emoji]", result.DisplayContent);
|
||||
Assert.AreEqual(4, result.Links.Count);
|
||||
|
||||
Link f = result.Links.Find(l => l.Url == "https://dev.ppy.sh/wiki/wiki links");
|
||||
Link f = result.Links.Find(l => l.Url == "https://osu.jvnko.boats/wiki/wiki links");
|
||||
Assert.That(f, Is.Not.Null);
|
||||
Assert.AreEqual(44, f.Index);
|
||||
Assert.AreEqual(10, f.Length);
|
||||
@@ -554,8 +554,8 @@ namespace osu.Game.Tests.Chat
|
||||
Assert.AreEqual("/relative", result.Argument);
|
||||
}
|
||||
|
||||
[TestCase("https://dev.ppy.sh/home/changelog", "")]
|
||||
[TestCase("https://dev.ppy.sh/home/changelog/lazer/2021.1012", "lazer/2021.1012")]
|
||||
[TestCase("https://osu.jvnko.boats/home/changelog", "")]
|
||||
[TestCase("https://osu.jvnko.boats/home/changelog/lazer/2021.1012", "lazer/2021.1012")]
|
||||
public void TestChangelogLinks(string link, string expectedArg)
|
||||
{
|
||||
LinkDetails result = MessageFormatter.GetLinkDetails(link);
|
||||
|
||||
@@ -134,10 +134,12 @@ namespace osu.Game.Tests.Mods
|
||||
|
||||
var mod = (OsuModDifficultyAdjust)apiMod.ToMod(ruleset);
|
||||
|
||||
// WARNING: this only makes sense for debug builds which have very extended limits
|
||||
// release builds still use sane values
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(mod.CircleSize.Value, Is.GreaterThanOrEqualTo(0).And.LessThanOrEqualTo(11));
|
||||
Assert.That(mod.ApproachRate.Value, Is.GreaterThanOrEqualTo(-10).And.LessThanOrEqualTo(11));
|
||||
Assert.That(mod.CircleSize.Value, Is.GreaterThanOrEqualTo(-250).And.LessThanOrEqualTo(13));
|
||||
Assert.That(mod.ApproachRate.Value, Is.GreaterThanOrEqualTo(-250).And.LessThanOrEqualTo(13));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// 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 NUnit.Framework;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Online.Multiplayer.MatchTypes.Matchmaking;
|
||||
@@ -149,5 +150,33 @@ namespace osu.Game.Tests.Online.Matchmaking
|
||||
Assert.AreEqual(5, state.Users.GetOrAdd(5).Placement);
|
||||
Assert.AreEqual(6, state.Users.GetOrAdd(6).Placement);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AbandonOrder()
|
||||
{
|
||||
var state = new MatchmakingRoomState();
|
||||
|
||||
state.AdvanceRound();
|
||||
state.RecordScores(
|
||||
[
|
||||
new SoloScoreInfo { UserID = 1, TotalScore = 1000 },
|
||||
new SoloScoreInfo { UserID = 2, TotalScore = 500 },
|
||||
], placement_points);
|
||||
|
||||
Assert.AreEqual(1, state.Users.GetOrAdd(1).Placement);
|
||||
Assert.AreEqual(2, state.Users.GetOrAdd(2).Placement);
|
||||
|
||||
state.Users.GetOrAdd(1).AbandonedAt = DateTimeOffset.Now;
|
||||
state.RecordScores([], placement_points);
|
||||
|
||||
Assert.AreEqual(2, state.Users.GetOrAdd(1).Placement);
|
||||
Assert.AreEqual(1, state.Users.GetOrAdd(2).Placement);
|
||||
|
||||
state.Users.GetOrAdd(2).AbandonedAt = DateTimeOffset.Now - TimeSpan.FromMinutes(1);
|
||||
state.RecordScores([], placement_points);
|
||||
|
||||
Assert.AreEqual(1, state.Users.GetOrAdd(1).Placement);
|
||||
Assert.AreEqual(2, state.Users.GetOrAdd(2).Placement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace osu.Game.Tests.Online
|
||||
Assert.NotNull(converted);
|
||||
Assert.That(converted, Is.TypeOf(typeof(UnknownMod)));
|
||||
Assert.That(converted.Type, Is.EqualTo(ModType.System));
|
||||
Assert.That(converted.Acronym, Is.EqualTo("WNG??"));
|
||||
Assert.That(converted.Acronym, Is.EqualTo("WNG!"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -225,7 +225,7 @@ namespace osu.Game.Tests.Online
|
||||
public override Live<BeatmapSetInfo>? ImportModel(BeatmapSetInfo item, ArchiveReader? archive = null, ImportParameters parameters = default,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (!testBeatmapManager.AllowImport.Wait(TimeSpan.FromSeconds(10), cancellationToken))
|
||||
if (!testBeatmapManager.AllowImport.Wait(TimeSpan.FromSeconds(30), cancellationToken))
|
||||
throw new TimeoutException("Timeout waiting for import to be allowed.");
|
||||
|
||||
return testBeatmapManager.CurrentImport = base.ImportModel(item, archive, parameters, cancellationToken);
|
||||
@@ -257,4 +257,4 @@ namespace osu.Game.Tests.Online
|
||||
protected override string Target => string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BIN
osu.Game.Tests/Resources/Archives/modified-classic-20250827.osk
Normal file
BIN
osu.Game.Tests/Resources/special-skin/score-0@2x.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
osu.Game.Tests/Resources/special-skin/score-1@2x.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
osu.Game.Tests/Resources/special-skin/score-2@2x.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
osu.Game.Tests/Resources/special-skin/score-3@2x.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
osu.Game.Tests/Resources/special-skin/score-4@2x.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
osu.Game.Tests/Resources/special-skin/score-5@2x.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
osu.Game.Tests/Resources/special-skin/score-6@2x.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
osu.Game.Tests/Resources/special-skin/score-7@2x.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
osu.Game.Tests/Resources/special-skin/score-8@2x.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
osu.Game.Tests/Resources/special-skin/score-9@2x.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
osu.Game.Tests/Resources/special-skin/score-comma@2x.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
osu.Game.Tests/Resources/special-skin/score-dot@2x.png
Normal file
|
After Width: | Height: | Size: 930 B |
BIN
osu.Game.Tests/Resources/special-skin/score-percent@2x.png
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
BIN
osu.Game.Tests/Resources/special-skin/score-pp@2x.png
Normal file
|
After Width: | Height: | Size: 4.7 KiB |
BIN
osu.Game.Tests/Resources/special-skin/score-x@2x.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
@@ -81,6 +81,8 @@ namespace osu.Game.Tests.Skins
|
||||
"Archives/modified-argon-20250809.osk",
|
||||
// Covers "Argon" judgement counter
|
||||
"Archives/modified-argon-20250308.osk",
|
||||
// Covers "Argon" clicks/s counter, longest combo counter, skinnable SR display and beatmap status pill
|
||||
"Archives/modified-argon-20251215-jvnkosu.osk",
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace osu.Game.Tests.Visual.Beatmaps
|
||||
AddStep("create thumbnail", () =>
|
||||
{
|
||||
var beatmapSet = CreateAPIBeatmapSet(Ruleset.Value);
|
||||
beatmapSet.OnlineID = 241526; // ID hardcoded to ensure that the preview track exists online.
|
||||
beatmapSet.OnlineID = 1; // ID hardcoded to ensure that the preview track exists online.
|
||||
|
||||
Child = thumbnail = new BeatmapCardThumbnail(beatmapSet, beatmapSet)
|
||||
{
|
||||
|
||||
@@ -106,7 +106,7 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
setUpEditor(new OsuRuleset().RulesetInfo);
|
||||
AddAssert("is osu! ruleset", () => editorBeatmap.BeatmapInfo.Ruleset.Equals(new OsuRuleset().RulesetInfo));
|
||||
|
||||
AddStep("jump to encoded link", () => Game.HandleLink("osu://edit/00:14:142%20(1)"));
|
||||
AddStep("jump to encoded link", () => Game.HandleLink("jvnkosu://edit/00:14:142%20(1)"));
|
||||
|
||||
AddUntilStep("wait for seek", () => editorClock.SeekingOrStopped.Value);
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
KeyCounter counter = null!;
|
||||
|
||||
loadPlayer(() => new OsuRuleset());
|
||||
AddStep("get key counter", () => counter = this.ChildrenOfType<KeyCounter>().Single(k => k.Trigger is KeyCounterActionTrigger<OsuAction> actionTrigger && actionTrigger.Action == OsuAction.LeftButton));
|
||||
AddStep("get key counter", () => counter = this.ChildrenOfType<KeyCounter>().Single(k => k.Trigger is KeyCounterBindingTrigger<OsuAction> actionTrigger && actionTrigger.Action == OsuAction.LeftButton));
|
||||
checkKey(() => counter, 0, false);
|
||||
|
||||
AddStep("press Z", () => InputManager.PressKey(Key.Z));
|
||||
@@ -117,7 +117,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
KeyCounter counter = null!;
|
||||
|
||||
loadPlayer(() => new ManiaRuleset());
|
||||
AddStep("get key counter", () => counter = this.ChildrenOfType<KeyCounter>().Single(k => k.Trigger is KeyCounterActionTrigger<ManiaAction> actionTrigger && actionTrigger.Action == ManiaAction.Key4));
|
||||
AddStep("get key counter", () => counter = this.ChildrenOfType<KeyCounter>().Single(k => k.Trigger is KeyCounterBindingTrigger<ManiaAction> actionTrigger && actionTrigger.Action == ManiaAction.Key4));
|
||||
checkKey(() => counter, 0, false);
|
||||
|
||||
AddStep("press space", () => InputManager.PressKey(Key.Space));
|
||||
@@ -150,8 +150,8 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
KeyCounter counterX = null!;
|
||||
|
||||
loadPlayer(() => new OsuRuleset());
|
||||
AddStep("get key counter Z", () => counterZ = this.ChildrenOfType<KeyCounter>().Single(k => k.Trigger is KeyCounterActionTrigger<OsuAction> actionTrigger && actionTrigger.Action == OsuAction.LeftButton));
|
||||
AddStep("get key counter X", () => counterX = this.ChildrenOfType<KeyCounter>().Single(k => k.Trigger is KeyCounterActionTrigger<OsuAction> actionTrigger && actionTrigger.Action == OsuAction.RightButton));
|
||||
AddStep("get key counter Z", () => counterZ = this.ChildrenOfType<KeyCounter>().Single(k => k.Trigger is KeyCounterBindingTrigger<OsuAction> actionTrigger && actionTrigger.Action == OsuAction.LeftButton));
|
||||
AddStep("get key counter X", () => counterX = this.ChildrenOfType<KeyCounter>().Single(k => k.Trigger is KeyCounterBindingTrigger<OsuAction> actionTrigger && actionTrigger.Action == OsuAction.RightButton));
|
||||
|
||||
AddStep("press Z", () => InputManager.PressKey(Key.Z));
|
||||
AddStep("pause", () => Player.Pause());
|
||||
@@ -184,7 +184,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
KeyCounter counter = null!;
|
||||
|
||||
loadPlayer(() => new ManiaRuleset());
|
||||
AddStep("get key counter", () => counter = this.ChildrenOfType<KeyCounter>().Single(k => k.Trigger is KeyCounterActionTrigger<ManiaAction> actionTrigger && actionTrigger.Action == ManiaAction.Key4));
|
||||
AddStep("get key counter", () => counter = this.ChildrenOfType<KeyCounter>().Single(k => k.Trigger is KeyCounterBindingTrigger<ManiaAction> actionTrigger && actionTrigger.Action == ManiaAction.Key4));
|
||||
|
||||
AddStep("press space", () => InputManager.PressKey(Key.Space));
|
||||
AddStep("pause", () => Player.Pause());
|
||||
@@ -204,8 +204,8 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
KeyCounter counterX = null!;
|
||||
|
||||
loadPlayer(() => new OsuRuleset());
|
||||
AddStep("get key counter Z", () => counterZ = this.ChildrenOfType<KeyCounter>().Single(k => k.Trigger is KeyCounterActionTrigger<OsuAction> actionTrigger && actionTrigger.Action == OsuAction.LeftButton));
|
||||
AddStep("get key counter X", () => counterX = this.ChildrenOfType<KeyCounter>().Single(k => k.Trigger is KeyCounterActionTrigger<OsuAction> actionTrigger && actionTrigger.Action == OsuAction.RightButton));
|
||||
AddStep("get key counter Z", () => counterZ = this.ChildrenOfType<KeyCounter>().Single(k => k.Trigger is KeyCounterBindingTrigger<OsuAction> actionTrigger && actionTrigger.Action == OsuAction.LeftButton));
|
||||
AddStep("get key counter X", () => counterX = this.ChildrenOfType<KeyCounter>().Single(k => k.Trigger is KeyCounterBindingTrigger<OsuAction> actionTrigger && actionTrigger.Action == OsuAction.RightButton));
|
||||
|
||||
AddStep("press Z", () => InputManager.PressKey(Key.Z));
|
||||
AddStep("pause", () => Player.Pause());
|
||||
@@ -247,7 +247,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
KeyCounter counter = null!;
|
||||
|
||||
loadPlayer(() => new ManiaRuleset());
|
||||
AddStep("get key counter", () => counter = this.ChildrenOfType<KeyCounter>().Single(k => k.Trigger is KeyCounterActionTrigger<ManiaAction> actionTrigger && actionTrigger.Action == ManiaAction.Key4));
|
||||
AddStep("get key counter", () => counter = this.ChildrenOfType<KeyCounter>().Single(k => k.Trigger is KeyCounterBindingTrigger<ManiaAction> actionTrigger && actionTrigger.Action == ManiaAction.Key4));
|
||||
|
||||
AddStep("press space", () => InputManager.PressKey(Key.Space));
|
||||
checkKey(() => counter, 1, true);
|
||||
@@ -271,7 +271,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
KeyCounter counter = null!;
|
||||
|
||||
loadPlayer(() => new OsuRuleset());
|
||||
AddStep("get key counter", () => counter = this.ChildrenOfType<KeyCounter>().Single(k => k.Trigger is KeyCounterActionTrigger<OsuAction> actionTrigger && actionTrigger.Action == OsuAction.LeftButton));
|
||||
AddStep("get key counter", () => counter = this.ChildrenOfType<KeyCounter>().Single(k => k.Trigger is KeyCounterBindingTrigger<OsuAction> actionTrigger && actionTrigger.Action == OsuAction.LeftButton));
|
||||
|
||||
AddStep("pause", () => Player.Pause());
|
||||
AddStep("resume", () => Player.Resume());
|
||||
@@ -297,7 +297,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
KeyCounter counter = null!;
|
||||
|
||||
loadPlayer(() => new OsuRuleset());
|
||||
AddStep("get key counter", () => counter = this.ChildrenOfType<KeyCounter>().Single(k => k.Trigger is KeyCounterActionTrigger<OsuAction> actionTrigger && actionTrigger.Action == OsuAction.LeftButton));
|
||||
AddStep("get key counter", () => counter = this.ChildrenOfType<KeyCounter>().Single(k => k.Trigger is KeyCounterBindingTrigger<OsuAction> actionTrigger && actionTrigger.Action == OsuAction.LeftButton));
|
||||
|
||||
AddStep("press Z", () => InputManager.PressKey(Key.Z));
|
||||
AddAssert("circle hit", () => Player.ScoreProcessor.HighestCombo.Value, () => Is.EqualTo(1));
|
||||
|
||||
@@ -642,7 +642,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
if (!AllowLoad.Wait(TimeSpan.FromSeconds(10)))
|
||||
if (!AllowLoad.Wait(TimeSpan.FromSeconds(30)))
|
||||
throw new TimeoutException();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Framework.Utils;
|
||||
@@ -26,8 +27,15 @@ namespace osu.Game.Tests.Visual.Matchmaking
|
||||
|
||||
AddStep("join room", () => JoinRoom(CreateDefaultRoom(MatchType.Matchmaking)));
|
||||
WaitForJoined();
|
||||
}
|
||||
|
||||
setupRequestHandler();
|
||||
[TestCase(2)]
|
||||
[TestCase(4)]
|
||||
[TestCase(8)]
|
||||
[TestCase(16)]
|
||||
public void TestDisplayScores(int scoreCount)
|
||||
{
|
||||
setupRequestHandler(scoreCount);
|
||||
|
||||
AddStep("load screen", () =>
|
||||
{
|
||||
@@ -40,7 +48,7 @@ namespace osu.Game.Tests.Visual.Matchmaking
|
||||
});
|
||||
}
|
||||
|
||||
private void setupRequestHandler()
|
||||
private void setupRequestHandler(int scoreCount)
|
||||
{
|
||||
AddStep("setup request handler", () =>
|
||||
{
|
||||
@@ -71,7 +79,7 @@ namespace osu.Game.Tests.Visual.Matchmaking
|
||||
case IndexPlaylistScoresRequest index:
|
||||
var result = new IndexedMultiplayerScores();
|
||||
|
||||
for (int i = 0; i < 8; ++i)
|
||||
for (int i = 0; i < scoreCount; ++i)
|
||||
{
|
||||
result.Scores.Add(new MultiplayerScore
|
||||
{
|
||||
|
||||
@@ -159,7 +159,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
AddStep("check request received", () =>
|
||||
{
|
||||
multiplayerClient.Verify(m => m.SendMatchRequest(It.Is<StartMatchCountdownRequest>(req =>
|
||||
req.Duration == TimeSpan.FromSeconds(10)
|
||||
req.Duration == TimeSpan.FromSeconds(30)
|
||||
)), Times.Once);
|
||||
});
|
||||
}
|
||||
@@ -181,7 +181,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
AddStep("check request received", () =>
|
||||
{
|
||||
multiplayerClient.Verify(m => m.SendMatchRequest(It.Is<StartMatchCountdownRequest>(req =>
|
||||
req.Duration == TimeSpan.FromSeconds(10)
|
||||
req.Duration == TimeSpan.FromSeconds(30)
|
||||
)), Times.Once);
|
||||
});
|
||||
|
||||
|
||||
@@ -305,6 +305,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
{
|
||||
new APIMod(new OsuModDoubleTime { SpeedChange = { Value = 2.0 } }),
|
||||
new APIMod(new OsuModStrictTracking()),
|
||||
new APIMod(new OsuModAutoplay()), // THIS IS PURELY TO ENABLE UNRANKED BADGE AND LET TEST PASS
|
||||
// I AM NOT PROUD OF THIS
|
||||
},
|
||||
AllowedMods = new[]
|
||||
{
|
||||
|
||||
@@ -387,7 +387,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
||||
{
|
||||
// Importantly, this occurs before base.load().
|
||||
if (!loader.AllowLoad.Wait(TimeSpan.FromSeconds(10)))
|
||||
if (!loader.AllowLoad.Wait(TimeSpan.FromSeconds(30)))
|
||||
throw new TimeoutException();
|
||||
|
||||
return base.CreateChildDependencies(parent);
|
||||
|
||||
@@ -920,8 +920,12 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Explicit("Featured Artist dialog is never displayed as the filter is disabled by default.")]
|
||||
public void TestFeaturedArtistDisclaimerDialog()
|
||||
{
|
||||
// NO-OP: FA dialog is not displayed ever
|
||||
|
||||
/*
|
||||
BeatmapListingOverlay getBeatmapListingOverlay() => Game.ChildrenOfType<BeatmapListingOverlay>().FirstOrDefault();
|
||||
|
||||
AddStep("Wait for notifications to load", () => Game.SearchBeatmapSet(string.Empty));
|
||||
@@ -939,6 +943,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
AddAssert("dialog dismissed", () => Game.ChildrenOfType<DialogOverlay>().Single().CurrentDialog == null);
|
||||
|
||||
AddUntilStep("featured artist filter is off", () => !getBeatmapListingOverlay().ChildrenOfType<BeatmapSearchGeneralFilterRow>().First().Current.Contains(SearchGeneral.FeaturedArtists));
|
||||
*/
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
private const int requested_beatmap_id = 75;
|
||||
private const int requested_beatmap_set_id = 1;
|
||||
|
||||
protected override TestOsuGame CreateTestGame() => new TestOsuGame(LocalStorage, API, new[] { $"osu://b/{requested_beatmap_id}" });
|
||||
protected override TestOsuGame CreateTestGame() => new TestOsuGame(LocalStorage, API, new[] { $"jvnkosu://b/{requested_beatmap_id}" });
|
||||
|
||||
[SetUp]
|
||||
public void Setup() => Schedule(() =>
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
{
|
||||
private const int requested_beatmap_set_id = 1;
|
||||
|
||||
protected override TestOsuGame CreateTestGame() => new TestOsuGame(LocalStorage, API, new[] { $"osu://s/{requested_beatmap_set_id}" });
|
||||
protected override TestOsuGame CreateTestGame() => new TestOsuGame(LocalStorage, API, new[] { $"jvnkosu://s/{requested_beatmap_set_id}" });
|
||||
|
||||
[SetUp]
|
||||
public void Setup() => Schedule(() =>
|
||||
|
||||
@@ -84,9 +84,9 @@ namespace osu.Game.Tests.Visual.Online
|
||||
public void TestFeaturedArtistFilter()
|
||||
{
|
||||
AddAssert("is visible", () => overlay.State.Value == Visibility.Visible);
|
||||
AddAssert("featured artist filter is on", () => overlay.ChildrenOfType<BeatmapSearchGeneralFilterRow>().First().Current.Contains(SearchGeneral.FeaturedArtists));
|
||||
AddStep("toggle featured artist filter", () => overlay.ChildrenOfType<FilterTabItem<SearchGeneral>>().First(i => i.Value == SearchGeneral.FeaturedArtists).TriggerClick());
|
||||
AddAssert("featured artist filter is off", () => !overlay.ChildrenOfType<BeatmapSearchGeneralFilterRow>().First().Current.Contains(SearchGeneral.FeaturedArtists));
|
||||
AddStep("toggle featured artist filter", () => overlay.ChildrenOfType<FilterTabItem<SearchGeneral>>().First(i => i.Value == SearchGeneral.FeaturedArtists).TriggerClick());
|
||||
AddAssert("featured artist filter is on", () => overlay.ChildrenOfType<BeatmapSearchGeneralFilterRow>().First().Current.Contains(SearchGeneral.FeaturedArtists));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -55,31 +55,31 @@ namespace osu.Game.Tests.Visual.Online
|
||||
});
|
||||
|
||||
[TestCase("test!")]
|
||||
[TestCase("dev.ppy.sh!")]
|
||||
[TestCase("https://dev.ppy.sh!", LinkAction.External)]
|
||||
[TestCase("http://dev.ppy.sh!", LinkAction.External)]
|
||||
[TestCase("forgothttps://dev.ppy.sh!", LinkAction.External)]
|
||||
[TestCase("forgothttp://dev.ppy.sh!", LinkAction.External)]
|
||||
[TestCase("osu.jvnko.boats!")]
|
||||
[TestCase("https://osu.jvnko.boats!", LinkAction.External)]
|
||||
[TestCase("http://osu.jvnko.boats!", LinkAction.External)]
|
||||
[TestCase("forgothttps://osu.jvnko.boats!", LinkAction.External)]
|
||||
[TestCase("forgothttp://osu.jvnko.boats!", LinkAction.External)]
|
||||
[TestCase("00:12:345 - Test?", LinkAction.OpenEditorTimestamp)]
|
||||
[TestCase("00:12:345 (1,2) - Test?", LinkAction.OpenEditorTimestamp)]
|
||||
[TestCase($"{OsuGameBase.OSU_PROTOCOL}edit/00:12:345 - Test?", LinkAction.OpenEditorTimestamp)]
|
||||
[TestCase($"{OsuGameBase.OSU_PROTOCOL}edit/00:12:345 (1,2) - Test?", LinkAction.OpenEditorTimestamp)]
|
||||
[TestCase($"{OsuGameBase.OSU_PROTOCOL}00:12:345 - not an editor timestamp", LinkAction.External)]
|
||||
[TestCase("Wiki link for tasty [[Performance Points]]", LinkAction.OpenWiki)]
|
||||
[TestCase("(osu forums)[https://dev.ppy.sh/forum] (old link format)", LinkAction.External)]
|
||||
[TestCase("[https://dev.ppy.sh/home New site] (new link format)", LinkAction.External)]
|
||||
[TestCase("[osu forums](https://dev.ppy.sh/forum) (new link format 2)", LinkAction.External)]
|
||||
[TestCase("[https://dev.ppy.sh/home This is only a link to the new osu webpage but this is supposed to test word wrap.]", LinkAction.External)]
|
||||
[TestCase("Let's (try)[https://dev.ppy.sh/home] [https://dev.ppy.sh/b/252238 multiple links] https://dev.ppy.sh/home", LinkAction.External, LinkAction.OpenBeatmap, LinkAction.External)]
|
||||
[TestCase("[https://dev.ppy.sh/home New link format with escaped [and \\[ paired] braces]", LinkAction.External)]
|
||||
[TestCase("[Markdown link format with escaped [and \\[ paired] braces](https://dev.ppy.sh/home)", LinkAction.External)]
|
||||
[TestCase("(Old link format with escaped (and \\( paired) parentheses)[https://dev.ppy.sh/home] and [[also a rogue wiki link]]", LinkAction.External, LinkAction.OpenWiki)]
|
||||
[TestCase("(osu forums)[https://osu.jvnko.boats/forum] (old link format)", LinkAction.External)]
|
||||
[TestCase("[https://osu.jvnko.boats/home New site] (new link format)", LinkAction.External)]
|
||||
[TestCase("[osu forums](https://osu.jvnko.boats/forum) (new link format 2)", LinkAction.External)]
|
||||
[TestCase("[https://osu.jvnko.boats/home This is only a link to the new osu webpage but this is supposed to test word wrap.]", LinkAction.External)]
|
||||
[TestCase("Let's (try)[https://osu.jvnko.boats/home] [https://osu.jvnko.boats/b/252238 multiple links] https://osu.jvnko.boats/home", LinkAction.External, LinkAction.OpenBeatmap, LinkAction.External)]
|
||||
[TestCase("[https://osu.jvnko.boats/home New link format with escaped [and \\[ paired] braces]", LinkAction.External)]
|
||||
[TestCase("[Markdown link format with escaped [and \\[ paired] braces](https://osu.jvnko.boats/home)", LinkAction.External)]
|
||||
[TestCase("(Old link format with escaped (and \\( paired) parentheses)[https://osu.jvnko.boats/home] and [[also a rogue wiki link]]", LinkAction.External, LinkAction.OpenWiki)]
|
||||
[TestCase("#lobby or #osu would be blue (and work) in the ChatDisplay test (when a proper ChatOverlay is present).")] // note that there's 0 links here (they get removed if a channel is not found)
|
||||
[TestCase("Join my multiplayer game osu://room/12346.", LinkAction.JoinRoom)]
|
||||
[TestCase("Join my multiplayer gameosu://room/12346.", LinkAction.JoinRoom)]
|
||||
[TestCase("Join my [multiplayer game](osu://room/12346).", LinkAction.JoinRoom)]
|
||||
[TestCase("Join my multiplayer game http://dev.ppy.sh/multiplayer/rooms/12346", LinkAction.JoinRoom)]
|
||||
[TestCase("Join my [multiplayer game](http://dev.ppy.sh/multiplayer/rooms/12346).", LinkAction.JoinRoom)]
|
||||
[TestCase("Join my multiplayer game jvnkosu://room/12346.", LinkAction.JoinRoom)]
|
||||
[TestCase("Join my multiplayer gamejvnkosu://room/12346.", LinkAction.JoinRoom)]
|
||||
[TestCase("Join my [multiplayer game](jvnkosu://room/12346).", LinkAction.JoinRoom)]
|
||||
[TestCase("Join my multiplayer game http://osu.jvnko.boats/multiplayer/rooms/12346", LinkAction.JoinRoom)]
|
||||
[TestCase("Join my [multiplayer game](http://osu.jvnko.boats/multiplayer/rooms/12346).", LinkAction.JoinRoom)]
|
||||
[TestCase($"Join my [#english]({OsuGameBase.OSU_PROTOCOL}chan/#english).", LinkAction.OpenChannel)]
|
||||
[TestCase($"Join my {OsuGameBase.OSU_PROTOCOL}chan/#english.", LinkAction.OpenChannel)]
|
||||
[TestCase($"Join my{OsuGameBase.OSU_PROTOCOL}chan/#english.", LinkAction.OpenChannel)]
|
||||
@@ -91,11 +91,11 @@ namespace osu.Game.Tests.Visual.Online
|
||||
addMessageWithChecks(text, expectedActions: actions);
|
||||
}
|
||||
|
||||
[TestCase("is now listening to [https://dev.ppy.sh/s/93523 IMAGE -MATERIAL- <Version 0>]", true, false, LinkAction.OpenBeatmapSet)]
|
||||
[TestCase("is now playing [https://dev.ppy.sh/b/252238 IMAGE -MATERIAL- <Version 0>]", true, false, LinkAction.OpenBeatmap)]
|
||||
[TestCase("is now listening to [https://osu.jvnko.boats/s/93523 IMAGE -MATERIAL- <Version 0>]", true, false, LinkAction.OpenBeatmapSet)]
|
||||
[TestCase("is now playing [https://osu.jvnko.boats/b/252238 IMAGE -MATERIAL- <Version 0>]", true, false, LinkAction.OpenBeatmap)]
|
||||
[TestCase("I am important!", false, true)]
|
||||
[TestCase("feels important", true, true)]
|
||||
[TestCase("likes to post this [https://dev.ppy.sh/home link].", true, true, LinkAction.External)]
|
||||
[TestCase("likes to post this [https://osu.jvnko.boats/home link].", true, true, LinkAction.External)]
|
||||
public void TestActionAndImportantLinks(string text, bool isAction, bool isImportant, params LinkAction[] expectedActions)
|
||||
{
|
||||
addMessageWithChecks(text, isAction, isImportant, expectedActions);
|
||||
@@ -135,9 +135,9 @@ namespace osu.Game.Tests.Visual.Online
|
||||
int messageIndex = 0;
|
||||
|
||||
addEchoWithWait("sent!", "received!");
|
||||
addEchoWithWait("https://dev.ppy.sh/home", null, 500);
|
||||
addEchoWithWait("[https://dev.ppy.sh/forum let's try multiple words too!]");
|
||||
addEchoWithWait("(long loading times! clickable while loading?)[https://dev.ppy.sh/home]", null, 5000);
|
||||
addEchoWithWait("https://osu.jvnko.boats/home", null, 500);
|
||||
addEchoWithWait("[https://osu.jvnko.boats/forum let's try multiple words too!]");
|
||||
addEchoWithWait("(long loading times! clickable while loading?)[https://osu.jvnko.boats/home]", null, 5000);
|
||||
|
||||
void addEchoWithWait(string text, string? completeText = null, double delay = 250)
|
||||
{
|
||||
|
||||
@@ -93,7 +93,7 @@ namespace osu.Game.Tests.Visual.Ranking
|
||||
AddStep("show example score", () =>
|
||||
{
|
||||
var score = TestResources.CreateTestScoreInfo(createTestBeatmap(new RealmUser()));
|
||||
score.Mods = score.Mods.Append(new OsuModDifficultyAdjust()).ToArray();
|
||||
score.Mods = score.Mods.Append(new OsuModAutoplay()).ToArray();
|
||||
showPanel(score);
|
||||
});
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
private void testInfoLabels(int expectedCount)
|
||||
{
|
||||
AddAssert("check info labels exists", () => infoWedge.Info.ChildrenOfType<BeatmapInfoWedge.WedgeInfoText.InfoLabel>().Any());
|
||||
AddAssert("check info labels count", () => infoWedge.Info.ChildrenOfType<BeatmapInfoWedge.WedgeInfoText.InfoLabel>().Count() == expectedCount);
|
||||
AddAssert("check info labels count", () => infoWedge.Info.ChildrenOfType<BeatmapInfoWedge.WedgeInfoText.InfoLabel>().Count() >= expectedCount);
|
||||
}
|
||||
|
||||
[SetUpSteps]
|
||||
|
||||
@@ -214,7 +214,7 @@ namespace osu.Game.Tests.Visual.SongSelectV2
|
||||
assertGroup(results, 3, "Pending", pendingBeatmap.Beatmaps, ref total);
|
||||
assertGroup(results, 4, "Graveyard", graveyardBeatmap.Beatmaps, ref total);
|
||||
assertGroup(results, 5, "Local", localBeatmap.Beatmaps, ref total);
|
||||
assertGroup(results, 6, "Unknown", noneBeatmap.Beatmaps, ref total);
|
||||
assertGroup(results, 6, "Offline", noneBeatmap.Beatmaps, ref total);
|
||||
assertGroup(results, 7, "Loved", lovedBeatmap.Beatmaps, ref total);
|
||||
assertTotal(results, total);
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ namespace osu.Game.Tests.Visual.SongSelectV2
|
||||
[Test]
|
||||
public void TestUnrankedBadge()
|
||||
{
|
||||
AddStep(@"Add unranked mod", () => changeMods(new[] { new OsuModDeflate() }));
|
||||
AddStep(@"Add unranked mod", () => changeMods(new[] { new OsuModAutoplay() }));
|
||||
AddUntilStep("Unranked badge shown", () => footerButtonMods.ChildrenOfType<FooterButtonMods.UnrankedBadge>().Single().Alpha == 1);
|
||||
AddStep(@"Clear selected mod", () => changeMods(Array.Empty<Mod>()));
|
||||
AddUntilStep("Unranked badge not shown", () => footerButtonMods.ChildrenOfType<FooterButtonMods.UnrankedBadge>().Single().Alpha == 0);
|
||||
|
||||
@@ -71,7 +71,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
[Test]
|
||||
public void TestUnrankedBadge()
|
||||
{
|
||||
AddStep(@"Add unranked mod", () => changeMods(new[] { new OsuModDeflate() }));
|
||||
AddStep(@"Add unranked mod", () => changeMods(new[] { new OsuModAutoplay() }));
|
||||
AddAssert("Unranked badge shown", () => footerButtonMods.UnrankedBadge.Alpha == 1);
|
||||
AddStep(@"Clear selected mod", () => changeMods(Array.Empty<Mod>()));
|
||||
AddAssert("Unranked badge not shown", () => footerButtonMods.UnrankedBadge.Alpha == 0);
|
||||
|
||||
@@ -129,8 +129,9 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
|
||||
setSliderValue("Circle Size", 99);
|
||||
|
||||
checkSliderAtValue("Circle Size", 11);
|
||||
checkBindableAtValue("Circle Size", 11);
|
||||
// debug build maximum value
|
||||
checkSliderAtValue("Circle Size", 13);
|
||||
checkBindableAtValue("Circle Size", 13);
|
||||
|
||||
setSliderValue("Approach Rate", -5);
|
||||
|
||||
|
||||
@@ -207,23 +207,23 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
|
||||
AddUntilStep("any column dimmed", () => this.ChildrenOfType<ModColumn>().Any(column => !column.Active.Value));
|
||||
|
||||
ModSelectColumn lastColumn = null!;
|
||||
ModSelectColumn secondColumn = null!;
|
||||
|
||||
AddAssert("last column dimmed", () => !this.ChildrenOfType<ModColumn>().Last().Active.Value);
|
||||
AddStep("request scroll to last column", () =>
|
||||
AddAssert("second column dimmed", () => !this.ChildrenOfType<ModColumn>().ElementAt(2).Active.Value);
|
||||
AddStep("request scroll to second column", () =>
|
||||
{
|
||||
var lastDimContainer = this.ChildrenOfType<ModSelectOverlay.ColumnDimContainer>().Last();
|
||||
lastColumn = lastDimContainer.Column;
|
||||
lastDimContainer.RequestScroll?.Invoke(lastDimContainer);
|
||||
var secondDimContainer = this.ChildrenOfType<ModSelectOverlay.ColumnDimContainer>().ElementAt(2);
|
||||
secondColumn = secondDimContainer.Column;
|
||||
secondDimContainer.RequestScroll?.Invoke(secondDimContainer);
|
||||
});
|
||||
AddUntilStep("column undimmed", () => lastColumn.Active.Value);
|
||||
AddUntilStep("column undimmed", () => secondColumn.Active.Value);
|
||||
|
||||
AddStep("click panel", () =>
|
||||
{
|
||||
InputManager.MoveMouseTo(lastColumn.ChildrenOfType<ModPanel>().First());
|
||||
InputManager.MoveMouseTo(secondColumn.ChildrenOfType<ModPanel>().First());
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
AddUntilStep("panel selected", () => lastColumn.ChildrenOfType<ModPanel>().First().Active.Value);
|
||||
AddUntilStep("panel selected", () => secondColumn.ChildrenOfType<ModPanel>().First().Active.Value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -810,7 +810,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
AddAssert("two columns visible", () => this.ChildrenOfType<ModColumn>().Count(col => col.IsPresent) == 2);
|
||||
|
||||
AddStep("unset filter", () => modSelectOverlay.IsValidMod = _ => true);
|
||||
AddAssert("all columns visible", () => this.ChildrenOfType<ModColumn>().All(col => col.IsPresent));
|
||||
AddAssert("all columns visible", () => this.ChildrenOfType<ModColumn>().Count(col => col.IsPresent) >= 4);
|
||||
|
||||
AddStep("filter out everything", () => modSelectOverlay.IsValidMod = _ => false);
|
||||
AddAssert("no columns visible", () => this.ChildrenOfType<ModColumn>().All(col => !col.IsPresent));
|
||||
@@ -839,7 +839,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
waitForColumnLoad();
|
||||
changeRuleset(0);
|
||||
|
||||
AddAssert("all columns visible", () => this.ChildrenOfType<ModColumn>().All(col => col.IsPresent));
|
||||
AddAssert("all columns visible", () => this.ChildrenOfType<ModColumn>().Count(col => col.IsPresent) >= 4);
|
||||
|
||||
AddStep("set search", () => modSelectOverlay.SearchTerm = "HD");
|
||||
AddAssert("two columns visible", () => this.ChildrenOfType<ModColumn>().Count(col => col.IsPresent) == 2);
|
||||
@@ -848,7 +848,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
AddAssert("no columns visible", () => this.ChildrenOfType<ModColumn>().All(col => !col.IsPresent));
|
||||
|
||||
AddStep("clear search bar", () => modSelectOverlay.SearchTerm = "");
|
||||
AddAssert("all columns visible", () => this.ChildrenOfType<ModColumn>().All(col => col.IsPresent));
|
||||
AddAssert("all columns visible", () => this.ChildrenOfType<ModColumn>().Count(col => col.IsPresent) >= 4);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -863,7 +863,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
waitForColumnLoad();
|
||||
changeRuleset(0);
|
||||
|
||||
AddAssert("all columns visible", () => this.ChildrenOfType<ModColumn>().All(col => col.IsPresent));
|
||||
AddAssert("all columns visible", () => this.ChildrenOfType<ModColumn>().Count(col => col.IsPresent) >= 4);
|
||||
|
||||
AddStep("set search", () => modSelectOverlay.SearchTerm = "fail");
|
||||
AddAssert("one column visible", () => this.ChildrenOfType<ModColumn>().Count(col => col.IsPresent) == 1);
|
||||
@@ -871,7 +871,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
AddStep("hide", () => modSelectOverlay.Hide());
|
||||
AddStep("show", () => modSelectOverlay.Show());
|
||||
|
||||
AddAssert("all columns visible", () => this.ChildrenOfType<ModColumn>().All(col => col.IsPresent));
|
||||
AddAssert("all columns visible", () => this.ChildrenOfType<ModColumn>().Count(col => col.IsPresent) >= 4);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -880,13 +880,13 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
createScreen();
|
||||
|
||||
changeRuleset(0);
|
||||
AddAssert("5 columns visible", () => this.ChildrenOfType<ModColumn>().Count(col => col.IsPresent) == 5);
|
||||
AddAssert("5 or more columns visible", () => this.ChildrenOfType<ModColumn>().Count(col => col.IsPresent) >= 5);
|
||||
|
||||
AddStep("change to ruleset without all mod types", () => Ruleset.Value = TestCustomisableModRuleset.CreateTestRulesetInfo());
|
||||
AddUntilStep("1 column visible", () => this.ChildrenOfType<ModColumn>().Count(col => col.IsPresent) == 1);
|
||||
|
||||
changeRuleset(0);
|
||||
AddAssert("5 columns visible", () => this.ChildrenOfType<ModColumn>().Count(col => col.IsPresent) == 5);
|
||||
AddAssert("5 or more columns visible", () => this.ChildrenOfType<ModColumn>().Count(col => col.IsPresent) >= 5);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -107,7 +107,7 @@ namespace osu.Game.Audio
|
||||
Logger.Log($"A {nameof(PreviewTrack)} was created without a containing {nameof(IPreviewTrackOwner)}. An owner should be added for correct behaviour.");
|
||||
}
|
||||
|
||||
protected override Track GetTrack() => trackManager.Get($"https://b.ppy.sh/preview/{beatmapSetInfo.OnlineID}.mp3");
|
||||
protected override Track GetTrack() => trackManager.Get($"https://osu.jvnko.boats/uploads/preview/{beatmapSetInfo.OnlineID}.mp3");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,6 +158,7 @@ namespace osu.Game.Configuration
|
||||
SetDefault(OsuSetting.ReplayPlaybackControlsExpanded, true);
|
||||
SetDefault(OsuSetting.GameplayLeaderboard, true);
|
||||
SetDefault(OsuSetting.AlwaysPlayFirstComboBreak, true);
|
||||
SetDefault(OsuSetting.AlwaysPlayComboBreak, false);
|
||||
|
||||
SetDefault(OsuSetting.FloatingComments, false);
|
||||
|
||||
@@ -369,6 +370,7 @@ namespace osu.Game.Configuration
|
||||
GameplayLeaderboard,
|
||||
PositionalHitsoundsLevel,
|
||||
AlwaysPlayFirstComboBreak,
|
||||
AlwaysPlayComboBreak,
|
||||
FloatingComments,
|
||||
HUDVisibilityMode,
|
||||
|
||||
|
||||
11
osu.Game/Configuration/WelcomeMusicMode.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
// 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.Configuration
|
||||
{
|
||||
public enum WelcomeMusicMode
|
||||
{
|
||||
Default,
|
||||
Custom
|
||||
}
|
||||
}
|
||||
@@ -214,7 +214,7 @@ namespace osu.Game.Database
|
||||
#if !DEBUG
|
||||
// in the lazer. straight up "migrating it". and by "it", haha, well. let's just say. My realm .
|
||||
string altFilename = filename;
|
||||
applyFilenameSchemaSuffix(ref altFilename); // it also migrates older versions automagically! (sorry, I only used that word for irony...)
|
||||
applyFilenameSchemaSuffix(ref altFilename);
|
||||
if (storage.Exists(altFilename) && !storage.Exists(Filename))
|
||||
{
|
||||
using (var previous = storage.GetStream(altFilename))
|
||||
@@ -222,6 +222,7 @@ namespace osu.Game.Database
|
||||
{
|
||||
Logger.Log($@"Migrating production build DB: {altFilename} -> {Filename}");
|
||||
previous.CopyTo(current);
|
||||
Logger.Log("Sucessfully migrated local database!", level: LogLevel.Important);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -124,10 +124,10 @@ namespace osu.Game.Graphics.Backgrounds
|
||||
api.PerformAsync(request);
|
||||
}
|
||||
|
||||
public SeasonalBackground LoadNextBackground()
|
||||
public Background LoadNextBackground()
|
||||
{
|
||||
if (!shouldShowCustomBackgrounds || !shouldFetchCustomBackgrounds || currentBackgrounds.Value?.Backgrounds?.Any() != true)
|
||||
return (SeasonalBackground)(new Background($@"Menu/menu-background-{RNG.Next(1, 9)}"));
|
||||
return new Background($@"Menu/menu-background-{RNG.Next(1, 9)}");
|
||||
|
||||
var backgrounds = currentBackgrounds.Value.Backgrounds;
|
||||
currentBackgroundIndex = (currentBackgroundIndex + 1) % backgrounds.Count;
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace osu.Game.Graphics.UserInterface
|
||||
}
|
||||
|
||||
[Resolved]
|
||||
protected OverlayColourProvider ColourProvider { get; private set; } = null!;
|
||||
protected OverlayColourProvider? ColourProvider { get; private set; } = null!;
|
||||
|
||||
private readonly Box background;
|
||||
private readonly OsuSpriteText text;
|
||||
@@ -190,9 +190,9 @@ namespace osu.Game.Graphics.UserInterface
|
||||
|
||||
private void updateState()
|
||||
{
|
||||
var colourDark = darkerColour ?? ColourProvider.Background3;
|
||||
var colourLight = lighterColour ?? ColourProvider.Background1;
|
||||
var colourContent = textColour ?? ColourProvider.Content1;
|
||||
var colourDark = darkerColour ?? ColourProvider?.Background3 ?? Colour4.DarkGray;
|
||||
var colourLight = lighterColour ?? ColourProvider?.Background1 ?? Colour4.LightGray;
|
||||
var colourContent = textColour ?? ColourProvider?.Content1 ?? Colour4.White;
|
||||
|
||||
if (!Enabled.Value)
|
||||
{
|
||||
|
||||
@@ -5,6 +5,7 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
|
||||
namespace osu.Game.Graphics.UserInterface
|
||||
{
|
||||
@@ -63,9 +64,9 @@ namespace osu.Game.Graphics.UserInterface
|
||||
|
||||
protected virtual void UpdateActiveState()
|
||||
{
|
||||
DarkerColour = Active.Value ? ColourProvider.Highlight1 : ColourProvider.Background3;
|
||||
LighterColour = Active.Value ? ColourProvider.Colour0 : ColourProvider.Background1;
|
||||
TextColour = Active.Value ? ColourProvider.Background6 : ColourProvider.Content1;
|
||||
DarkerColour = Active.Value ? ColourProvider?.Highlight1 ?? Colour4.Gray : ColourProvider?.Background3 ?? Colour4.DimGray;
|
||||
LighterColour = Active.Value ? ColourProvider?.Colour0 ?? Colour4.AliceBlue : ColourProvider?.Background1 ?? Colour4.LightGray;
|
||||
TextColour = Active.Value ? ColourProvider?.Background6 ?? Colour4.Black : ColourProvider?.Content1 ?? Colour4.DarkGray;
|
||||
}
|
||||
|
||||
private void playSample()
|
||||
|
||||
@@ -603,7 +603,7 @@ namespace osu.Game.Online.API
|
||||
cancellationToken.Cancel();
|
||||
}
|
||||
|
||||
private class WebRequestFlushedException : Exception
|
||||
internal class WebRequestFlushedException : Exception
|
||||
{
|
||||
public WebRequestFlushedException(APIState state)
|
||||
: base($@"Request failed from flush operation (state {state})")
|
||||
|
||||
12
osu.Game/Online/API/Requests/GetMusicCategoriesRequest.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
// 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.Game.Online.API.Requests.Responses;
|
||||
|
||||
namespace osu.Game.Online.API.Requests
|
||||
{
|
||||
public class GetMusicCategoriesRequest : APIRequest<APIBackgroundCategories>
|
||||
{
|
||||
protected override string Target => @"https://osu.jvnko.boats/welcome-music/categories";
|
||||
}
|
||||
}
|
||||
21
osu.Game/Online/API/Requests/GetWelcomeMusicRequest.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.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
|
||||
namespace osu.Game.Online.API.Requests
|
||||
{
|
||||
public class GetWelcomeMusicRequest : APIRequest<List<APIWelcomeMusic>>
|
||||
{
|
||||
private readonly string category;
|
||||
|
||||
public GetWelcomeMusicRequest(string category)
|
||||
{
|
||||
this.category = category;
|
||||
}
|
||||
|
||||
protected override string Target => $"https://osu.jvnko.boats/welcome-music/list?category={WebUtility.UrlEncode(category)}";
|
||||
}
|
||||
}
|
||||
17
osu.Game/Online/API/Requests/Responses/APIWelcomeMusic.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace osu.Game.Online.API.Requests.Responses
|
||||
{
|
||||
// Описывает один трек, как он приходит с сервера
|
||||
public class APIWelcomeMusic
|
||||
{
|
||||
[JsonProperty("name")]
|
||||
public string? Name { get; set; }
|
||||
|
||||
[JsonProperty("url")]
|
||||
public string? Url { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,7 @@ namespace osu.Game.Online.Chat
|
||||
// http[s]://<domain>.<tld>[:port][/path][?query][#fragment]
|
||||
private static readonly Regex advanced_link_regex = new Regex(
|
||||
// protocol
|
||||
@"(?<link>(https?|osu(mp)?):\/\/" +
|
||||
@"(?<link>(https?|jvnkosu(mp)?):\/\/" +
|
||||
// domain + tld
|
||||
@"(?<domain>(?:[a-z0-9]\.|[a-z0-9][a-z0-9-]*[a-z0-9]\.)*[a-z0-9-]*[a-z0-9]" +
|
||||
// port (optional)
|
||||
@@ -60,7 +60,7 @@ namespace osu.Game.Online.Chat
|
||||
.Split('/').Last(); // only keep domain name, ignoring protocol.
|
||||
}
|
||||
|
||||
private static string websiteRootUrl = "osu.ppy.sh";
|
||||
private static string websiteRootUrl = "osu.jvnko.boats";
|
||||
|
||||
private static void handleMatches(Regex regex, string display, string link, MessageFormatterResult result, int startIndex = 0, LinkAction? linkActionOverride = null, char[]? escapeChars = null)
|
||||
{
|
||||
@@ -211,7 +211,7 @@ namespace osu.Game.Online.Chat
|
||||
|
||||
break;
|
||||
|
||||
case @"osu":
|
||||
case @"jvnkosu":
|
||||
// every internal link also needs some kind of argument
|
||||
if (args.Length < 3)
|
||||
break;
|
||||
|
||||
@@ -153,7 +153,7 @@ namespace osu.Game.Online.Multiplayer
|
||||
/// <summary>
|
||||
/// Signals that a user has requested to skip the beatmap intro.
|
||||
/// </summary>
|
||||
Task UserVotedToSkipIntro(int userId);
|
||||
Task UserVotedToSkipIntro(int userId, bool voted);
|
||||
|
||||
/// <summary>
|
||||
/// Signals that the vote to skip the beatmap intro has passed.
|
||||
|
||||
@@ -36,5 +36,11 @@ namespace osu.Game.Online.Multiplayer.MatchTypes.Matchmaking
|
||||
/// </summary>
|
||||
[Key(3)]
|
||||
public MatchmakingRoundList Rounds { get; set; } = new MatchmakingRoundList();
|
||||
|
||||
/// <summary>
|
||||
/// The time at which this user abandoned the match.
|
||||
/// </summary>
|
||||
[Key(4)]
|
||||
public DateTimeOffset? AbandonedAt { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,42 +23,53 @@ namespace osu.Game.Online.Multiplayer.MatchTypes.Matchmaking
|
||||
ArgumentNullException.ThrowIfNull(x);
|
||||
ArgumentNullException.ThrowIfNull(y);
|
||||
|
||||
// X appears earlier in the list if it has more points.
|
||||
if (x.Points > y.Points)
|
||||
return -1;
|
||||
int compare = compareAbandonedAt(x, y);
|
||||
if (compare != 0)
|
||||
return compare;
|
||||
|
||||
// Y appears earlier in the list if it has more points.
|
||||
if (y.Points > x.Points)
|
||||
return 1;
|
||||
compare = comparePoints(x, y);
|
||||
if (compare != 0)
|
||||
return compare;
|
||||
|
||||
// Tiebreaker 1 (likely): From each user's point-of-view, their earliest and best placement.
|
||||
compare = compareRoundPlacements(x, y);
|
||||
if (compare != 0)
|
||||
return compare;
|
||||
|
||||
return compareUserIds(x, y);
|
||||
}
|
||||
|
||||
private int compareAbandonedAt(MatchmakingUser x, MatchmakingUser y)
|
||||
{
|
||||
DateTimeOffset xAbandonedAt = x.AbandonedAt ?? DateTimeOffset.MaxValue;
|
||||
DateTimeOffset yAbandonedAt = y.AbandonedAt ?? DateTimeOffset.MaxValue;
|
||||
return -xAbandonedAt.CompareTo(yAbandonedAt);
|
||||
}
|
||||
|
||||
private int comparePoints(MatchmakingUser x, MatchmakingUser y)
|
||||
{
|
||||
return -x.Points.CompareTo(y.Points);
|
||||
}
|
||||
|
||||
private int compareRoundPlacements(MatchmakingUser x, MatchmakingUser y)
|
||||
{
|
||||
for (int r = 1; r <= rounds; r++)
|
||||
{
|
||||
MatchmakingRound? xRound;
|
||||
x.Rounds.RoundsDictionary.TryGetValue(r, out xRound);
|
||||
x.Rounds.RoundsDictionary.TryGetValue(r, out var xRound);
|
||||
y.Rounds.RoundsDictionary.TryGetValue(r, out var yRound);
|
||||
|
||||
MatchmakingRound? yRound;
|
||||
y.Rounds.RoundsDictionary.TryGetValue(r, out yRound);
|
||||
int xPlacement = xRound?.Placement ?? int.MaxValue;
|
||||
int yPlacement = yRound?.Placement ?? int.MaxValue;
|
||||
|
||||
// Nothing to do if both players haven't played this round.
|
||||
if (xRound == null && yRound == null)
|
||||
continue;
|
||||
|
||||
// X appears later in the list if it hasn't played this round.
|
||||
if (xRound == null)
|
||||
return 1;
|
||||
|
||||
// Y appears later in the list if it hasn't played this round.
|
||||
if (yRound == null)
|
||||
return -1;
|
||||
|
||||
// X appears earlier in the list if it has a better placement in the round.
|
||||
int compare = xRound.Placement.CompareTo(yRound.Placement);
|
||||
int compare = xPlacement.CompareTo(yPlacement);
|
||||
if (compare != 0)
|
||||
return compare;
|
||||
}
|
||||
|
||||
// Tiebreaker 2 (unlikely): User ID.
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int compareUserIds(MatchmakingUser x, MatchmakingUser y)
|
||||
{
|
||||
return x.UserId.CompareTo(y.UserId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ namespace osu.Game.Online.Multiplayer
|
||||
public event Action<int, long>? MatchmakingItemDeselected;
|
||||
public event Action<MatchRoomState>? MatchRoomStateChanged;
|
||||
|
||||
public event Action<int>? UserVotedToSkipIntro;
|
||||
public event Action<int, bool>? UserVotedToSkipIntro;
|
||||
public event Action? VoteToSkipIntroPassed;
|
||||
|
||||
public event Action<MultiplayerRoomUser, BeatmapAvailability>? BeatmapAvailabilityChanged;
|
||||
@@ -854,10 +854,6 @@ namespace osu.Game.Online.Multiplayer
|
||||
handleRoomRequest(() =>
|
||||
{
|
||||
Debug.Assert(Room != null);
|
||||
|
||||
foreach (var user in Room.Users)
|
||||
user.VotedToSkipIntro = false;
|
||||
|
||||
GameplayStarted?.Invoke();
|
||||
});
|
||||
|
||||
@@ -928,7 +924,7 @@ namespace osu.Game.Online.Multiplayer
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
Task IMultiplayerClient.UserVotedToSkipIntro(int userId)
|
||||
Task IMultiplayerClient.UserVotedToSkipIntro(int userId, bool voted)
|
||||
{
|
||||
handleRoomRequest(() =>
|
||||
{
|
||||
@@ -940,9 +936,8 @@ namespace osu.Game.Online.Multiplayer
|
||||
if (user == null)
|
||||
return;
|
||||
|
||||
user.VotedToSkipIntro = true;
|
||||
|
||||
UserVotedToSkipIntro?.Invoke(userId);
|
||||
user.VotedToSkipIntro = voted;
|
||||
UserVotedToSkipIntro?.Invoke(userId, voted);
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
@@ -1117,7 +1112,7 @@ namespace osu.Game.Online.Multiplayer
|
||||
|
||||
Task IMatchmakingClient.MatchmakingItemSelected(int userId, long playlistItemId)
|
||||
{
|
||||
Scheduler.Add(() =>
|
||||
handleRoomRequest(() =>
|
||||
{
|
||||
MatchmakingItemSelected?.Invoke(userId, playlistItemId);
|
||||
RoomUpdated?.Invoke();
|
||||
@@ -1128,7 +1123,7 @@ namespace osu.Game.Online.Multiplayer
|
||||
|
||||
Task IMatchmakingClient.MatchmakingItemDeselected(int userId, long playlistItemId)
|
||||
{
|
||||
Scheduler.Add(() =>
|
||||
handleRoomRequest(() =>
|
||||
{
|
||||
MatchmakingItemDeselected?.Invoke(userId, playlistItemId);
|
||||
RoomUpdated?.Invoke();
|
||||
|
||||
@@ -70,7 +70,7 @@ namespace osu.Game.Online.Multiplayer
|
||||
connection.On<MultiplayerPlaylistItem>(nameof(IMultiplayerClient.PlaylistItemAdded), ((IMultiplayerClient)this).PlaylistItemAdded);
|
||||
connection.On<long>(nameof(IMultiplayerClient.PlaylistItemRemoved), ((IMultiplayerClient)this).PlaylistItemRemoved);
|
||||
connection.On<MultiplayerPlaylistItem>(nameof(IMultiplayerClient.PlaylistItemChanged), ((IMultiplayerClient)this).PlaylistItemChanged);
|
||||
connection.On<int>(nameof(IMultiplayerClient.UserVotedToSkipIntro), ((IMultiplayerClient)this).UserVotedToSkipIntro);
|
||||
connection.On<int, bool>(nameof(IMultiplayerClient.UserVotedToSkipIntro), ((IMultiplayerClient)this).UserVotedToSkipIntro);
|
||||
connection.On(nameof(IMultiplayerClient.VoteToSkipIntroPassed), ((IMultiplayerClient)this).VoteToSkipIntroPassed);
|
||||
|
||||
connection.On(nameof(IMatchmakingClient.MatchmakingQueueJoined), ((IMatchmakingClient)this).MatchmakingQueueJoined);
|
||||
|
||||
@@ -81,7 +81,7 @@ namespace osu.Game
|
||||
public const string GAME_NAME = "jvnkosu!";
|
||||
#endif
|
||||
|
||||
public const string OSU_PROTOCOL = "jnvkosu://";
|
||||
public const string OSU_PROTOCOL = "jvnkosu://";
|
||||
|
||||
/// <summary>
|
||||
/// The filename of the main client database.
|
||||
|
||||
@@ -84,8 +84,12 @@ namespace osu.Game.Overlays
|
||||
|
||||
performAfterFetch(() =>
|
||||
{
|
||||
string versionPart = version.Split('-')[0];
|
||||
string updateStream = version.Split('-')[1];
|
||||
string[] versionIdentifier = version.Split('-');
|
||||
|
||||
string versionPart = versionIdentifier[0];
|
||||
string updateStream = versionIdentifier.Length >= 2
|
||||
? versionIdentifier[1]
|
||||
: "lazer"; // let's assume it's lazer by default, seems like the most sane option
|
||||
|
||||
var build = builds.Find(b => b.Version == versionPart && b.UpdateStream.Name == updateStream)
|
||||
?? Streams.Find(s => s.Name == updateStream)?.LatestBuild;
|
||||
|
||||
@@ -54,9 +54,9 @@ namespace osu.Game.Overlays.Mods
|
||||
|
||||
protected override void UpdateActiveState()
|
||||
{
|
||||
DarkerColour = Active.Value ? colours.Orange1 : ColourProvider.Background3;
|
||||
LighterColour = Active.Value ? colours.Orange0 : ColourProvider.Background1;
|
||||
TextColour = Active.Value ? ColourProvider.Background6 : ColourProvider.Content1;
|
||||
DarkerColour = Active.Value ? colours.Orange1 : ColourProvider?.Background3 ?? Colour4.DarkGray;
|
||||
LighterColour = Active.Value ? colours.Orange0 : ColourProvider?.Background1 ?? Colour4.LightGray;
|
||||
TextColour = Active.Value ? ColourProvider?.Background6 ?? Colour4.Black : ColourProvider?.Content1 ?? Colour4.Gray;
|
||||
|
||||
if (Active.Value)
|
||||
this.ShowPopover();
|
||||
|
||||
@@ -438,7 +438,9 @@ namespace osu.Game.Overlays.Mods
|
||||
|
||||
foreach (var modState in AllAvailableMods)
|
||||
{
|
||||
var matchingSelectedMod = SelectedMods.Value.SingleOrDefault(selected => selected.GetType() == modState.Mod.GetType());
|
||||
// BUG: when trying to switch ruleset in a multiplayer room this was previously throwing an InvalidOperationException.
|
||||
// If it still throws, then I guess it's not good
|
||||
var matchingSelectedMod = SelectedMods.Value.FirstOrDefault(selected => selected.GetType() == modState.Mod.GetType());
|
||||
|
||||
if (matchingSelectedMod != null)
|
||||
{
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace osu.Game.Overlays.Profile.Sections.Recent
|
||||
private readonly string slug;
|
||||
private readonly Sprite sprite;
|
||||
|
||||
private string url => $@"https://s.ppy.sh/images/medals-client/{slug}@2x.png";
|
||||
private string url => $@"https://osu.jvnko.boats/images/medals-client/{slug}@2x.png";
|
||||
|
||||
public MedalIcon(string slug)
|
||||
{
|
||||
|
||||
@@ -13,6 +13,9 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay
|
||||
{
|
||||
protected override LocalisableString Header => GameplaySettingsStrings.AudioHeader;
|
||||
|
||||
private SettingsCheckbox alwaysPlayFirst = null!;
|
||||
private SettingsCheckbox alwaysPlay = null!;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuConfigManager config, OsuConfigManager osuConfig)
|
||||
{
|
||||
@@ -26,13 +29,23 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay
|
||||
KeyboardStep = 0.01f,
|
||||
DisplayAsPercentage = true
|
||||
},
|
||||
new SettingsCheckbox
|
||||
alwaysPlayFirst = new SettingsCheckbox
|
||||
{
|
||||
ClassicDefault = false,
|
||||
LabelText = GameplaySettingsStrings.AlwaysPlayFirstComboBreak,
|
||||
Current = config.GetBindable<bool>(OsuSetting.AlwaysPlayFirstComboBreak)
|
||||
},
|
||||
alwaysPlay = new SettingsCheckbox
|
||||
{
|
||||
ClassicDefault = false,
|
||||
LabelText = "Always play combo break sound",
|
||||
Current = config.GetBindable<bool>(OsuSetting.AlwaysPlayComboBreak)
|
||||
}
|
||||
};
|
||||
alwaysPlay.Current.BindValueChanged(d =>
|
||||
{
|
||||
alwaysPlayFirst.Current.Disabled = d.NewValue;
|
||||
}, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// 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.
|
||||
|
||||
#nullable disable
|
||||
#nullable enable
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
@@ -19,19 +19,22 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface
|
||||
{
|
||||
protected override LocalisableString Header => UserInterfaceStrings.MainMenuHeader;
|
||||
|
||||
[Resolved]
|
||||
private SeasonalBackgroundLoader backgroundLoader { get; set; }
|
||||
// TODO: refactor seasonal bg code to the way it was before options were introduced
|
||||
private SeasonalBackgroundLoader? backgroundLoader = null!;
|
||||
|
||||
private IBindable<APIUser> user;
|
||||
private IBindable<APIUser> user = null!;
|
||||
|
||||
private SettingsEnumDropdown<BackgroundSource> backgroundSourceDropdown;
|
||||
private SettingsEnumDropdown<BackgroundSource> backgroundSourceDropdown = null!;
|
||||
|
||||
private Bindable<bool> useSeasonalBackgrounds;
|
||||
private Bindable<bool> useSeasonalBackgrounds = null!;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuConfigManager config, IAPIProvider api)
|
||||
private void load(OsuConfigManager config, IAPIProvider api, SeasonalBackgroundLoader? backgroundLoader)
|
||||
{
|
||||
user = api.LocalUser.GetBoundCopy();
|
||||
|
||||
this.backgroundLoader = backgroundLoader;
|
||||
|
||||
useSeasonalBackgrounds = config.GetBindable<bool>(OsuSetting.UseSeasonalBackgroundsV2);
|
||||
|
||||
var backgroundToggle = new SettingsCheckbox
|
||||
@@ -50,17 +53,17 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface
|
||||
var refreshButton = new SettingsButton
|
||||
{
|
||||
Text = UserInterfaceStrings.SeasonalBackgroundsRefresh,
|
||||
Action = () => backgroundLoader.RefreshCategories()
|
||||
Action = () => backgroundLoader?.RefreshCategories()
|
||||
};
|
||||
|
||||
// TODO: the category dropdown disappear if no backgrounds (e.g. when first enabling the setting)
|
||||
refreshButton.CanBeShown.BindTo(useSeasonalBackgrounds);
|
||||
categoryDropdown.CanBeShown.BindTo(useSeasonalBackgrounds);
|
||||
useSeasonalBackgrounds.BindValueChanged(
|
||||
_ => backgroundLoader.RefreshCategories(true)
|
||||
_ => backgroundLoader?.RefreshCategories(true)
|
||||
);
|
||||
|
||||
backgroundLoader.AvailableCategories.BindValueChanged(categories => categoryDropdown.Items = categories.NewValue, true);
|
||||
backgroundLoader?.AvailableCategories.BindValueChanged(categories => categoryDropdown.Items = categories.NewValue, true);
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
|
||||
@@ -25,6 +25,7 @@ using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Input.Bindings;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
@@ -44,7 +45,7 @@ namespace osu.Game.Overlays.Volume
|
||||
private readonly Color4 meterColour;
|
||||
private readonly string name;
|
||||
|
||||
private OsuSpriteText text;
|
||||
private ArgonCounterTextComponent text { get; set; }
|
||||
private BufferedContainer maxGlow;
|
||||
|
||||
private Container selectedGlowContainer;
|
||||
@@ -199,12 +200,7 @@ namespace osu.Game.Overlays.Volume
|
||||
Radius = 10,
|
||||
}
|
||||
},
|
||||
maxGlow = (text = new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Font = OsuFont.Numeric.With(size: 0.16f * CircleSize)
|
||||
}).WithEffect(new GlowEffect
|
||||
maxGlow = (text = new ArgonCounterTextComponent(Anchor.Centre)).WithEffect(new GlowEffect
|
||||
{
|
||||
Colour = Color4.Transparent,
|
||||
PadExtent = true,
|
||||
@@ -239,6 +235,8 @@ namespace osu.Game.Overlays.Volume
|
||||
|
||||
Bindable.BindValueChanged(volume => { this.TransformTo(nameof(DisplayVolume), volume.NewValue, 400, Easing.OutQuint); }, true);
|
||||
|
||||
text.Scale = new Vector2(0.9f);
|
||||
text.WireframeOpacity.BindTo(new BindableFloat(0.5f));
|
||||
bgProgress.Progress = 0.75f;
|
||||
}
|
||||
|
||||
@@ -257,17 +255,16 @@ namespace osu.Game.Overlays.Volume
|
||||
bool intVolumeChanged = intValue != displayVolumeInt;
|
||||
|
||||
displayVolumeInt = intValue;
|
||||
|
||||
text.WireframeTemplate = new string('#', intValue.ToString(CultureInfo.CurrentCulture).Length);
|
||||
text.Text = intValue.ToString(CultureInfo.CurrentCulture);
|
||||
|
||||
if (displayVolume >= 0.995f)
|
||||
{
|
||||
text.Text = "MAX";
|
||||
maxGlow.EffectColour = meterColour.Opacity(2f);
|
||||
}
|
||||
maxGlow.EffectColour = meterColour.Opacity(5f);
|
||||
else if (displayVolume < 0.01f)
|
||||
maxGlow.EffectColour = meterColour.Opacity(0f);
|
||||
else
|
||||
{
|
||||
maxGlow.EffectColour = Color4.Transparent;
|
||||
text.Text = intValue.ToString(CultureInfo.CurrentCulture);
|
||||
}
|
||||
maxGlow.EffectColour = meterColour.Opacity((float)displayVolume * 3f + 1f);
|
||||
|
||||
volumeCircle.Progress = displayVolume * 0.75f;
|
||||
volumeCircleGlow.Progress = displayVolume * 0.75f;
|
||||
|
||||
@@ -29,6 +29,14 @@ namespace osu.Game.Rulesets.Mods
|
||||
|
||||
private Action? triggerFailureDelegate;
|
||||
|
||||
// NOTE: when processing serialized replays with both these values enabled, only `Exit`'s value is applied.
|
||||
// I guess that's reasonable and doesn't break much.
|
||||
public ModFailCondition()
|
||||
{
|
||||
Restart.BindValueChanged(d => { if (d.NewValue) Exit.Value = false; });
|
||||
Exit.BindValueChanged(d => { if (d.NewValue) Restart.Value = false; });
|
||||
}
|
||||
|
||||
public void ApplyToHealthProcessor(HealthProcessor healthProcessor)
|
||||
{
|
||||
triggerFailureDelegate = healthProcessor.TriggerFailure;
|
||||
|
||||
@@ -1,47 +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.Collections.Generic;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Overlays.Settings;
|
||||
|
||||
namespace osu.Game.Rulesets.Mods
|
||||
{
|
||||
public abstract class ModRateAdjustConcrete : ModRateAdjust
|
||||
{
|
||||
public override string Name => "Rate Adjust";
|
||||
public override LocalisableString Description => "[DEBUG BUILDS ONLY] Set any speed";
|
||||
public override string Acronym => "_R";
|
||||
private readonly RateAdjustModHelper rateAdjustHelper;
|
||||
|
||||
[SettingSource("Speed decrease", "The actual decrease to apply", SettingControlType = typeof(MultiplierSettingsSlider))]
|
||||
public override BindableNumber<double> SpeedChange { get; } = new BindableDouble(0.75)
|
||||
{
|
||||
MinValue = 0.1, // BASS breaks at lower rates
|
||||
MaxValue = 10,
|
||||
Precision = 0.01
|
||||
};
|
||||
|
||||
[SettingSource("Adjust pitch", "Should pitch be adjusted with speed")]
|
||||
public virtual BindableBool AdjustPitch { get; } = new BindableBool();
|
||||
|
||||
|
||||
protected ModRateAdjustConcrete()
|
||||
{
|
||||
rateAdjustHelper = new RateAdjustModHelper(SpeedChange);
|
||||
rateAdjustHelper.HandleAudioAdjustments(AdjustPitch);
|
||||
}
|
||||
|
||||
public override double ScoreMultiplier => 1.0;
|
||||
public override void ApplyToTrack(IAdjustableAudioComponent track)
|
||||
{
|
||||
rateAdjustHelper.ApplyToTrack(track);
|
||||
}
|
||||
public override bool Ranked => false;
|
||||
public override ModType Type => ModType.Special;
|
||||
}
|
||||
}
|
||||
@@ -159,8 +159,9 @@ namespace osu.Game.Rulesets.UI
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
Alpha = 0,
|
||||
Font = OsuFont.Numeric.With(size: 22f, weight: FontWeight.Black),
|
||||
UseFullGlyphHeight = false,
|
||||
Font = OsuFont.TorusAlternate.With(size: 36, weight: FontWeight.SemiBold),
|
||||
Margin = new MarginPadding { Bottom = 5 },
|
||||
UseFullGlyphHeight = true,
|
||||
Text = mod.Acronym
|
||||
},
|
||||
modIcon = new SpriteIcon
|
||||
|
||||
@@ -91,11 +91,12 @@ namespace osu.Game.Rulesets.UI
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Shadow = false,
|
||||
Font = OsuFont.Numeric.With(size: 24, weight: FontWeight.Black),
|
||||
Font = OsuFont.TorusAlternate.With(size: 36, weight: FontWeight.Bold),
|
||||
Text = mod.Acronym,
|
||||
Margin = new MarginPadding
|
||||
{
|
||||
Top = 4
|
||||
Top = 3,
|
||||
Bottom = 6
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.Match
|
||||
resetPlaceholderText();
|
||||
|
||||
TextBox.HoldFocus = false;
|
||||
TextBox.ReleaseFocusOnCommit = true;
|
||||
TextBox.ReleaseFocusOnCommit = false;
|
||||
TextBox.Focus = () => TextBox.PlaceholderText = ChatStrings.InputPlaceholder;
|
||||
TextBox.FocusLost = resetPlaceholderText;
|
||||
|
||||
|
||||
@@ -520,6 +520,9 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.Match
|
||||
|
||||
private void onBeatmapAvailabilityChanged(MultiplayerRoomUser user, BeatmapAvailability availability) => Scheduler.Add(() =>
|
||||
{
|
||||
if (!user.Equals(RoomUser))
|
||||
return;
|
||||
|
||||
if (availability.State == DownloadState.Downloading)
|
||||
downloadProgressBar.FadeIn(200, Easing.OutPow10);
|
||||
else
|
||||
|
||||
@@ -23,6 +23,7 @@ using osu.Game.Online.Rooms;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Screens.Ranking;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Screens.OnlinePlay.Matchmaking.Match.RoundResults
|
||||
{
|
||||
@@ -31,8 +32,6 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.Match.RoundResults
|
||||
/// </summary>
|
||||
public partial class SubScreenRoundResults : MatchmakingSubScreen
|
||||
{
|
||||
private const int panel_spacing = 5;
|
||||
|
||||
public override PanelDisplayStyle PlayersDisplayStyle => PanelDisplayStyle.Hidden;
|
||||
public override Drawable? PlayersDisplayArea => null;
|
||||
|
||||
@@ -51,7 +50,7 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.Match.RoundResults
|
||||
[Resolved]
|
||||
private RulesetStore rulesets { get; set; } = null!;
|
||||
|
||||
private AutoScrollContainer scrollContainer = null!;
|
||||
private PanelContainer panelContainer = null!;
|
||||
private LoadingSpinner loadingSpinner = null!;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
@@ -59,7 +58,7 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.Match.RoundResults
|
||||
{
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
scrollContainer = new AutoScrollContainer
|
||||
panelContainer = new PanelContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both
|
||||
},
|
||||
@@ -136,78 +135,57 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.Match.RoundResults
|
||||
|
||||
private void setScores(ScoreInfo[] scores) => Scheduler.Add(() =>
|
||||
{
|
||||
Container panels;
|
||||
|
||||
scrollContainer.Child = panels = new Container
|
||||
panelContainer.ChildrenEnumerable = scores.Select(s => new RoundResultsScorePanel(s)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Width = scores.Length * (ScorePanel.CONTRACTED_WIDTH + panel_spacing),
|
||||
ChildrenEnumerable = scores.Select(s => new RoundResultsScorePanel(s)
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft
|
||||
})
|
||||
};
|
||||
|
||||
for (int i = 0; i < panels.Count; i++)
|
||||
{
|
||||
panels[i].MoveToX(panels.DrawWidth * 2)
|
||||
.Delay(i * 100)
|
||||
.MoveToX((ScorePanel.CONTRACTED_WIDTH + panel_spacing) * i, 500, Easing.OutQuint);
|
||||
}
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre
|
||||
});
|
||||
});
|
||||
|
||||
private partial class RoundResultsScorePanel : CompositeDrawable
|
||||
{
|
||||
public RoundResultsScorePanel(ScoreInfo score)
|
||||
{
|
||||
AutoSizeAxes = Axes.Both;
|
||||
InternalChild = new InstantSizingScorePanel(score);
|
||||
Size = new Vector2(ScorePanel.CONTRACTED_WIDTH, ScorePanel.CONTRACTED_HEIGHT);
|
||||
|
||||
InternalChild = new ScorePanel(score);
|
||||
}
|
||||
|
||||
public override bool PropagateNonPositionalInputSubTree => false;
|
||||
public override bool PropagatePositionalInputSubTree => false;
|
||||
|
||||
private partial class InstantSizingScorePanel : ScorePanel
|
||||
{
|
||||
public InstantSizingScorePanel(ScoreInfo score, bool isNewLocalScore = false)
|
||||
: base(score, isNewLocalScore)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
FinishTransforms(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private partial class AutoScrollContainer : UserTrackingScrollContainer
|
||||
private partial class PanelContainer : Container<RoundResultsScorePanel>
|
||||
{
|
||||
private const float initial_offset = -0.5f;
|
||||
private const double scroll_duration = 20000;
|
||||
protected override Container<RoundResultsScorePanel> Content => flowContainer;
|
||||
|
||||
private double? scrollStartTime;
|
||||
private readonly Container centreingContainer;
|
||||
private readonly Container<RoundResultsScorePanel> flowContainer;
|
||||
|
||||
public AutoScrollContainer()
|
||||
: base(Direction.Horizontal)
|
||||
public PanelContainer()
|
||||
{
|
||||
InternalChild = new OsuScrollContainer(Direction.Horizontal)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = centreingContainer = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Child = flowContainer = new FillFlowContainer<RoundResultsScorePanel>
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
AutoSizeAxes = Axes.X,
|
||||
Spacing = new Vector2(5)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
if (!UserScrolling && Children.Count > 0)
|
||||
{
|
||||
scrollStartTime ??= Time.Current;
|
||||
|
||||
double scrollOffset = (Time.Current - scrollStartTime.Value) / scroll_duration;
|
||||
|
||||
if (scrollOffset < 1)
|
||||
ScrollTo(DrawWidth * (initial_offset + scrollOffset), false);
|
||||
}
|
||||
centreingContainer.Width = Math.Max(DrawWidth, flowContainer.DrawWidth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
|
||||
private void onUserStateChanged(MultiplayerRoomUser user, MultiplayerUserState state) => Schedule(updateCount);
|
||||
|
||||
private void onUserVotedToSkipIntro(int userId) => Schedule(() =>
|
||||
private void onUserVotedToSkipIntro(int userId, bool voted) => Schedule(() =>
|
||||
{
|
||||
FadingContent.TriggerShow();
|
||||
updateCount();
|
||||
|
||||
@@ -21,6 +21,8 @@ namespace osu.Game.Screens.Play
|
||||
|
||||
private Bindable<bool> alwaysPlayFirst;
|
||||
|
||||
private Bindable<bool> alwaysPlay;
|
||||
|
||||
private double? firstBreakTime;
|
||||
|
||||
public ComboEffects(ScoreProcessor processor)
|
||||
@@ -33,6 +35,7 @@ namespace osu.Game.Screens.Play
|
||||
{
|
||||
InternalChild = comboBreakSample = new SkinnableSound(new SampleInfo("Gameplay/combobreak"));
|
||||
alwaysPlayFirst = config.GetBindable<bool>(OsuSetting.AlwaysPlayFirstComboBreak);
|
||||
alwaysPlay = config.GetBindable<bool>(OsuSetting.AlwaysPlayComboBreak);
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
@@ -56,7 +59,7 @@ namespace osu.Game.Screens.Play
|
||||
if (gameplayClock.IsRewinding)
|
||||
return;
|
||||
|
||||
if (combo.NewValue == 0 && (combo.OldValue > 20 || (alwaysPlayFirst.Value && firstBreakTime == null)))
|
||||
if (combo.NewValue == 0 && (combo.OldValue > 20 || (alwaysPlayFirst.Value && firstBreakTime == null) || alwaysPlay.Value))
|
||||
{
|
||||
firstBreakTime = gameplayClock.CurrentTime;
|
||||
|
||||
|
||||
@@ -18,14 +18,12 @@ using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Graphics.UserInterfaceV2;
|
||||
using osu.Game.Input.Bindings;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Resources.Localisation.Web;
|
||||
using osu.Game.Utils;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace osu.Game.Screens.Play
|
||||
{
|
||||
@@ -73,8 +71,6 @@ namespace osu.Game.Screens.Play
|
||||
[Resolved]
|
||||
private GlobalActionContainer globalAction { get; set; } = null!;
|
||||
|
||||
private ShearedButton saveReplay { get; set; } = null!;
|
||||
|
||||
protected GameplayMenuOverlay()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
@@ -124,15 +120,20 @@ namespace osu.Game.Screens.Play
|
||||
Radius = 50
|
||||
},
|
||||
},
|
||||
saveReplay = new ShearedButton
|
||||
{
|
||||
Text = "Quit and save replay",
|
||||
Origin = Anchor.TopCentre,
|
||||
Anchor = Anchor.TopCentre,
|
||||
Height = 32,
|
||||
Colour = colours.PurpleLight,
|
||||
// Visibility = false
|
||||
},
|
||||
|
||||
// XXX: I have mixed feelings about this, but it works at least
|
||||
(OnQuitReplay != null)
|
||||
? new ShearedButton
|
||||
{
|
||||
Text = "Quit and save replay",
|
||||
Origin = Anchor.TopCentre,
|
||||
Anchor = Anchor.TopCentre,
|
||||
Height = 32,
|
||||
Colour = colours.PurpleLight,
|
||||
Action = () => OnQuitReplay.Invoke()
|
||||
}
|
||||
: [],
|
||||
|
||||
playInfoText = new OsuTextFlowContainer(cp => cp.Font = OsuFont.GetFont(size: 18))
|
||||
{
|
||||
Origin = Anchor.TopCentre,
|
||||
@@ -153,12 +154,6 @@ namespace osu.Game.Screens.Play
|
||||
if (OnQuit != null)
|
||||
AddButton(GameplayMenuOverlayStrings.Quit, new Color4(170, 27, 39, 255), () => OnQuit.Invoke());
|
||||
|
||||
if (OnQuitReplay != null)
|
||||
{
|
||||
// saveReplay.Visibility = true;
|
||||
saveReplay.Action = () => OnQuitReplay.Invoke();
|
||||
}
|
||||
|
||||
State.ValueChanged += _ => InternalButtons.Deselect();
|
||||
|
||||
updateInfoText();
|
||||
|
||||
@@ -519,7 +519,7 @@ namespace osu.Game.Screens.Play
|
||||
Retries = RestartCount,
|
||||
OnRetry = () => Restart(),
|
||||
OnQuit = () => PerformExitWithConfirmation(),
|
||||
OnQuitReplay = () => PerformExitReplay()
|
||||
OnQuitReplay = (this is not SoloPlayer) ? null : PerformExitReplay
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -998,13 +998,10 @@ namespace osu.Game.Screens.Play
|
||||
PauseOverlay.Hide();
|
||||
|
||||
bool exitOnFail = GameplayState.Mods.OfType<IApplicableFailExit>().Any(m => m.ExitOnFail)
|
||||
&& Score.ScoreInfo.User.Username == config.Get<string>(OsuSetting.Username); // TODO: do more concrete checks
|
||||
&& Score.ScoreInfo.User.Username == config.Get<string>(OsuSetting.Username)
|
||||
&& this is SoloPlayer;
|
||||
if (exitOnFail)
|
||||
{
|
||||
// game.AttemptExit();
|
||||
game.Exit();
|
||||
}
|
||||
|
||||
game.Exit(); // we're done here
|
||||
|
||||
bool restartOnFail = GameplayState.Mods.OfType<IApplicableFailOverride>().Any(m => m.RestartOnFail);
|
||||
if (!restartOnFail)
|
||||
|
||||
@@ -122,9 +122,9 @@ namespace osu.Game.Screens.Ranking.Expanded
|
||||
FillMode = FillMode.Fit,
|
||||
}
|
||||
},
|
||||
scoreCounter = new TotalScoreCounter(!withFlair)
|
||||
scoreCounter = new TotalScoreCounter(!withFlair, score)
|
||||
{
|
||||
Margin = new MarginPadding { Top = 0, Bottom = 5 },
|
||||
Margin = new MarginPadding { Top = 10, Bottom = 5 },
|
||||
Current = { Value = 0 },
|
||||
Alpha = 0,
|
||||
AlwaysPresent = true
|
||||
|
||||
@@ -1,17 +1,23 @@
|
||||
// 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.
|
||||
|
||||
#nullable disable
|
||||
#nullable enable
|
||||
|
||||
using System.Globalization;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Audio;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Scoring.Legacy;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using osu.Game.Screens.Ranking.Expanded.Accuracy;
|
||||
using osuTK;
|
||||
|
||||
@@ -30,43 +36,65 @@ namespace osu.Game.Screens.Ranking.Expanded
|
||||
|
||||
private readonly Bindable<double> tickPlaybackRate = new Bindable<double>();
|
||||
|
||||
private ScoreInfo score;
|
||||
private Bindable<ScoringMode> scoringMode = new Bindable<ScoringMode>(ScoringMode.Standardised);
|
||||
private ScoringMode mode => scoringMode.Value;
|
||||
|
||||
private double lastSampleTime;
|
||||
|
||||
private DrawableSample sampleTick;
|
||||
private DrawableSample sampleTick = null!;
|
||||
private ArgonCounterTextComponent counter = null!;
|
||||
|
||||
public TotalScoreCounter(bool playSamples = false)
|
||||
public TotalScoreCounter(bool playSamples = false, ScoreInfo? score = null)
|
||||
{
|
||||
// Todo: AutoSize X removed here due to https://github.com/ppy/osu-framework/issues/3369
|
||||
AutoSizeAxes = Axes.Y;
|
||||
RelativeSizeAxes = Axes.X;
|
||||
|
||||
this.playSamples = playSamples;
|
||||
this.score = score ?? new ScoreInfo();
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(AudioManager audio)
|
||||
private void load(AudioManager audio, OsuConfigManager? config)
|
||||
{
|
||||
AddInternal(sampleTick = new DrawableSample(audio.Samples.Get(@"Results/score-tick-lesser")));
|
||||
scoringMode.BindTo(
|
||||
config?.GetBindable<ScoringMode>(OsuSetting.ScoreDisplayMode)
|
||||
);
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
scoringMode.BindValueChanged(_ => updateWireframe(), true);
|
||||
|
||||
|
||||
if (playSamples)
|
||||
Current.BindValueChanged(_ => startTicking());
|
||||
}
|
||||
|
||||
protected override LocalisableString FormatCount(long count) => count.ToString("N0");
|
||||
protected override LocalisableString FormatCount(long count) => count.ToString("N0", CultureInfo.CreateSpecificCulture("en-US")).Replace(',', '.'); // XXX: make this look okay
|
||||
|
||||
protected override OsuSpriteText CreateSpriteText() => base.CreateSpriteText().With(s =>
|
||||
private void updateWireframe()
|
||||
{
|
||||
s.Anchor = Anchor.TopCentre;
|
||||
s.Origin = Anchor.TopCentre;
|
||||
string getWireframe(long sc) => (sc >= 100000)
|
||||
? FormatCount(sc).ToString()
|
||||
: "###.###";
|
||||
|
||||
s.Font = OsuFont.Torus.With(size: 60, weight: FontWeight.Light, fixedWidth: true);
|
||||
s.Spacing = new Vector2(-5, 0);
|
||||
});
|
||||
long dispScore = Scoring.Legacy.ScoreInfoExtensions.GetDisplayScore(score, mode);
|
||||
counter.WireframeTemplate = getWireframe(dispScore);
|
||||
}
|
||||
|
||||
protected override ArgonCounterTextComponent CreateText()
|
||||
{
|
||||
counter = new ArgonCounterTextComponent(Anchor.Centre);
|
||||
counter.WireframeOpacity.BindTo(new BindableFloat(0.25f));
|
||||
counter.WireframeTemplate = "###.###";
|
||||
|
||||
return counter;
|
||||
}
|
||||
|
||||
public override long DisplayedCount
|
||||
{
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace osu.Game.Screens.Ranking
|
||||
/// <summary>
|
||||
/// Height of the panel when contracted.
|
||||
/// </summary>
|
||||
private const float contracted_height = 385;
|
||||
public const float CONTRACTED_HEIGHT = 385;
|
||||
|
||||
/// <summary>
|
||||
/// Width of the panel when expanded.
|
||||
@@ -280,7 +280,7 @@ namespace osu.Game.Screens.Ranking
|
||||
break;
|
||||
|
||||
case PanelState.Contracted:
|
||||
Size = new Vector2(CONTRACTED_WIDTH, contracted_height);
|
||||
Size = new Vector2(CONTRACTED_WIDTH, CONTRACTED_HEIGHT);
|
||||
|
||||
topLayerBackground.FadeColour(getColour(contracted_top_layer_colour), RESIZE_DURATION, Easing.OutQuint);
|
||||
middleLayerBackground.FadeColour(getColour(contracted_middle_layer_colour), RESIZE_DURATION, Easing.OutQuint);
|
||||
|
||||
@@ -270,7 +270,7 @@ namespace osu.Game.Screens.Select
|
||||
TextSize = 11,
|
||||
TextPadding = new MarginPadding { Horizontal = 8, Vertical = 2 },
|
||||
Status = beatmapInfo.Status,
|
||||
ShowUnknownStatus = true,
|
||||
ShowUnknownStatus = working is not DummyWorkingBeatmap,
|
||||
Alpha = string.IsNullOrEmpty(beatmapInfo.DifficultyName) ? 0 : 1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -308,7 +308,7 @@ namespace osu.Game.Screens.SelectV2
|
||||
{
|
||||
perf = (float)Math.Round((float?)d.NewValue.PerformanceAttributes?.Total ?? 0f, 1); // yikes
|
||||
var arr = difficultyStatisticsDisplay.Statistics.ToArray();
|
||||
arr[0] = new StatisticDifficulty.Data("Max PP", perf, perf, perf);
|
||||
if (arr.Length >= 1) arr[0] = new StatisticDifficulty.Data("Max PP", perf, perf, perf);
|
||||
difficultyStatisticsDisplay.Statistics = arr.AsEnumerable();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -105,7 +105,7 @@ namespace osu.Game.Screens.SelectV2
|
||||
new ShearAligningWrapper(statusPill = new BeatmapSetOnlineStatusPill
|
||||
{
|
||||
Shear = -OsuGame.SHEAR,
|
||||
ShowUnknownStatus = true,
|
||||
ShowUnknownStatus = working is not DummyWorkingBeatmap,
|
||||
TextSize = OsuFont.Style.Caption1.Size,
|
||||
TextPadding = new MarginPadding { Horizontal = 6, Vertical = 1 },
|
||||
}),
|
||||
|
||||
44
osu.Game/Skinning/LegacyPerformancePointsCounter.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
// 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.Graphics;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Skinning
|
||||
{
|
||||
public partial class LegacyPerformancePointsCounter : PerformancePointsCounter, ISerialisableDrawable
|
||||
{
|
||||
protected override double RollingDuration => 1000;
|
||||
protected override Easing RollingEasing => Easing.Out;
|
||||
|
||||
private const float alpha_when_invalid = 0.3f;
|
||||
|
||||
public LegacyPerformancePointsCounter()
|
||||
{
|
||||
Anchor = Anchor.TopRight;
|
||||
Origin = Anchor.TopRight;
|
||||
|
||||
Scale = new Vector2(0.96f);
|
||||
}
|
||||
|
||||
public override bool IsValid
|
||||
{
|
||||
get => base.IsValid;
|
||||
set
|
||||
{
|
||||
if (value == IsValid)
|
||||
return;
|
||||
|
||||
base.IsValid = value;
|
||||
DrawableCount.FadeTo(value ? 1 : alpha_when_invalid, 1000, Easing.OutQuint);
|
||||
}
|
||||
}
|
||||
|
||||
protected override LocalisableString FormatCount(int count) => count.ToString($@"0'{LegacySpriteText.PP_SUFFIX_CHAR}'");
|
||||
|
||||
protected sealed override OsuSpriteText CreateSpriteText() => new LegacySpriteText(LegacyFont.Score);
|
||||
}
|
||||
}
|
||||
@@ -568,7 +568,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
|
||||
public async Task UserVoteToSkipIntro(int userId)
|
||||
{
|
||||
await ((IMultiplayerClient)this).UserVotedToSkipIntro(userId).ConfigureAwait(false);
|
||||
await ((IMultiplayerClient)this).UserVotedToSkipIntro(userId, true).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
protected override Task<MultiplayerRoom> CreateRoomInternal(MultiplayerRoom room)
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace osu.Game.Users
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string InternalName { get; set; }
|
||||
public string ImageUrl => $@"https://s.ppy.sh/images/medals-client/{InternalName}@2x.png";
|
||||
public string ImageUrl => $@"https://osu.jvnko.boats/images/medals/{InternalName}@2x.png";
|
||||
public string Description { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,14 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Net.WebSockets;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
@@ -17,6 +21,7 @@ using osu.Game.Beatmaps;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Models;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Rulesets;
|
||||
@@ -219,20 +224,35 @@ namespace osu.Game.Utils
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly HashSet<int> ignored_io_exception_hresults =
|
||||
[
|
||||
// see https://stackoverflow.com/a/9294382 for how these are synthesised
|
||||
unchecked((int)0x80070020), // ERROR_SHARING_VIOLATION
|
||||
unchecked((int)0x80070027), // ERROR_HANDLE_DISK_FULL
|
||||
unchecked((int)0x80070070), // ERROR_DISK_FULL
|
||||
];
|
||||
|
||||
private bool shouldSubmitException(Exception exception)
|
||||
{
|
||||
switch (exception)
|
||||
{
|
||||
case IOException ioe:
|
||||
// disk full exceptions, see https://stackoverflow.com/a/9294382
|
||||
const int hr_error_handle_disk_full = unchecked((int)0x80070027);
|
||||
const int hr_error_disk_full = unchecked((int)0x80070070);
|
||||
// disk I/O failures, invalid formats, etc.
|
||||
|
||||
if (ioe.HResult == hr_error_handle_disk_full || ioe.HResult == hr_error_disk_full)
|
||||
case IOException ioe:
|
||||
if (ignored_io_exception_hresults.Contains(ioe.HResult))
|
||||
return false;
|
||||
|
||||
break;
|
||||
|
||||
case UnauthorizedAccessException:
|
||||
case SharpCompress.Common.InvalidFormatException:
|
||||
return false;
|
||||
|
||||
// connectivity failures
|
||||
|
||||
case TimeoutException te:
|
||||
return !te.Message.Contains(@"elapsed without receiving a message from the server");
|
||||
|
||||
case WebException we:
|
||||
switch (we.Status)
|
||||
{
|
||||
@@ -242,6 +262,16 @@ namespace osu.Game.Utils
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case WebSocketException:
|
||||
case SocketException:
|
||||
return false;
|
||||
|
||||
// stuff that should really never make it to sentry
|
||||
|
||||
case APIAccess.WebRequestFlushedException:
|
||||
case TaskCanceledException:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Realm" Version="20.1.0" />
|
||||
<PackageReference Include="ppy.osu.Framework" Version="2025.1205.1" />
|
||||
<PackageReference Include="ppy.osu.Framework" Version="2025.1209.0" />
|
||||
<PackageReference Include="jvnkosu.Resources" Version="2025.1119.0" />
|
||||
<PackageReference Include="Sentry" Version="5.1.1" />
|
||||
<!-- Held back due to 0.34.0 failing AOT compilation on ZstdSharp.dll dependency. -->
|
||||
|
||||