mirror of
https://github.com/ppy/osu.git
synced 2025-01-13 17:13:06 +08:00
Merge branch 'master' into fix-mania-normalised-scroll-speed
This commit is contained in:
commit
e6368fd6b2
@ -52,7 +52,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2022.109.0" />
|
||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2022.107.0" />
|
||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2022.111.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Label="Transitive Dependencies">
|
||||
<!-- Realm needs to be directly referenced in all Xamarin projects, as it will not pull in its transitive dependencies otherwise. -->
|
||||
|
@ -48,7 +48,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
||||
if (mods.Any(m => m is OsuModNoFail))
|
||||
multiplier *= Math.Max(0.90, 1.0 - 0.02 * effectiveMissCount);
|
||||
|
||||
if (mods.Any(m => m is OsuModSpunOut))
|
||||
if (mods.Any(m => m is OsuModSpunOut) && totalHits > 0)
|
||||
multiplier *= 1.0 - Math.Pow((double)Attributes.SpinnerCount / totalHits, 0.85);
|
||||
|
||||
if (mods.Any(h => h is OsuModRelax))
|
||||
|
@ -9,6 +9,21 @@ namespace osu.Game.Tests.Chat
|
||||
[TestFixture]
|
||||
public class MessageFormatterTests
|
||||
{
|
||||
private string originalWebsiteRootUrl;
|
||||
|
||||
[OneTimeSetUp]
|
||||
public void OneTimeSetUp()
|
||||
{
|
||||
originalWebsiteRootUrl = MessageFormatter.WebsiteRootUrl;
|
||||
MessageFormatter.WebsiteRootUrl = "dev.ppy.sh";
|
||||
}
|
||||
|
||||
[OneTimeTearDown]
|
||||
public void OneTimeTearDown()
|
||||
{
|
||||
MessageFormatter.WebsiteRootUrl = originalWebsiteRootUrl;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestBareLink()
|
||||
{
|
||||
@ -32,8 +47,6 @@ namespace osu.Game.Tests.Chat
|
||||
[TestCase(LinkAction.External, "https://dev.ppy.sh/beatmapsets/discussions/123", "https://dev.ppy.sh/beatmapsets/discussions/123")]
|
||||
public void TestBeatmapLinks(LinkAction expectedAction, string expectedArg, string link)
|
||||
{
|
||||
MessageFormatter.WebsiteRootUrl = "dev.ppy.sh";
|
||||
|
||||
Message result = MessageFormatter.FormatMessage(new Message { Content = link });
|
||||
|
||||
Assert.AreEqual(result.Content, result.DisplayContent);
|
||||
@ -47,7 +60,10 @@ namespace osu.Game.Tests.Chat
|
||||
[Test]
|
||||
public void TestMultipleComplexLinks()
|
||||
{
|
||||
Message result = MessageFormatter.FormatMessage(new Message { Content = "This is a http://test.io/link#fragment. (see https://twitter.com). Also, This string should not be altered. http://example.com/" });
|
||||
Message result = MessageFormatter.FormatMessage(new Message
|
||||
{
|
||||
Content = "This is a http://test.io/link#fragment. (see https://twitter.com). Also, This string should not be altered. http://example.com/"
|
||||
});
|
||||
|
||||
Assert.AreEqual(result.Content, result.DisplayContent);
|
||||
Assert.AreEqual(3, result.Links.Count);
|
||||
@ -104,7 +120,7 @@ namespace osu.Game.Tests.Chat
|
||||
|
||||
Assert.AreEqual("This is a Wiki Link.", result.DisplayContent);
|
||||
Assert.AreEqual(1, result.Links.Count);
|
||||
Assert.AreEqual("https://osu.ppy.sh/wiki/Wiki Link", result.Links[0].Url);
|
||||
Assert.AreEqual("https://dev.ppy.sh/wiki/Wiki Link", result.Links[0].Url);
|
||||
Assert.AreEqual(10, result.Links[0].Index);
|
||||
Assert.AreEqual(9, result.Links[0].Length);
|
||||
}
|
||||
@ -117,15 +133,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://osu.ppy.sh/wiki/Wiki Link", result.Links[0].Url);
|
||||
Assert.AreEqual("https://dev.ppy.sh/wiki/Wiki Link", result.Links[0].Url);
|
||||
Assert.AreEqual(10, result.Links[0].Index);
|
||||
Assert.AreEqual(9, result.Links[0].Length);
|
||||
|
||||
Assert.AreEqual("https://osu.ppy.sh/wiki/Wiki:Link", result.Links[1].Url);
|
||||
Assert.AreEqual("https://dev.ppy.sh/wiki/Wiki:Link", result.Links[1].Url);
|
||||
Assert.AreEqual(20, result.Links[1].Index);
|
||||
Assert.AreEqual(9, result.Links[1].Length);
|
||||
|
||||
Assert.AreEqual("https://osu.ppy.sh/wiki/Wiki.Link", result.Links[2].Url);
|
||||
Assert.AreEqual("https://dev.ppy.sh/wiki/Wiki.Link", result.Links[2].Url);
|
||||
Assert.AreEqual(29, result.Links[2].Index);
|
||||
Assert.AreEqual(9, result.Links[2].Length);
|
||||
}
|
||||
@ -445,12 +461,15 @@ namespace osu.Game.Tests.Chat
|
||||
[Test]
|
||||
public void TestLinkComplex()
|
||||
{
|
||||
Message result = MessageFormatter.FormatMessage(new Message { Content = "This is a [http://www.simple-test.com simple test] with some [traps] and [[wiki links]]. Don't forget to visit https://osu.ppy.sh (now!)[http://google.com]\uD83D\uDE12" });
|
||||
Message result = MessageFormatter.FormatMessage(new Message
|
||||
{
|
||||
Content = "This is a [http://www.simple-test.com simple test] with some [traps] and [[wiki links]]. Don't forget to visit https://osu.ppy.sh (now!)[http://google.com]\uD83D\uDE12"
|
||||
});
|
||||
|
||||
Assert.AreEqual("This is a simple test with some [traps] and wiki links. Don't forget to visit https://osu.ppy.sh now!\0\0\0", result.DisplayContent);
|
||||
Assert.AreEqual(5, result.Links.Count);
|
||||
|
||||
Link f = result.Links.Find(l => l.Url == "https://osu.ppy.sh/wiki/wiki links");
|
||||
Link f = result.Links.Find(l => l.Url == "https://dev.ppy.sh/wiki/wiki links");
|
||||
Assert.That(f, Is.Not.Null);
|
||||
Assert.AreEqual(44, f.Index);
|
||||
Assert.AreEqual(10, f.Length);
|
||||
@ -514,8 +533,6 @@ namespace osu.Game.Tests.Chat
|
||||
[TestCase("https://dev.ppy.sh/home/changelog/lazer/2021.1012", "lazer/2021.1012")]
|
||||
public void TestChangelogLinks(string link, string expectedArg)
|
||||
{
|
||||
MessageFormatter.WebsiteRootUrl = "dev.ppy.sh";
|
||||
|
||||
LinkDetails result = MessageFormatter.GetLinkDetails(link);
|
||||
|
||||
Assert.AreEqual(LinkAction.OpenChangelog, result.Action);
|
||||
|
@ -50,63 +50,24 @@ namespace osu.Game.Tests.Visual.Online
|
||||
|
||||
Dependencies.Cache(new ChatOverlay());
|
||||
Dependencies.Cache(dialogOverlay);
|
||||
|
||||
testLinksGeneral();
|
||||
testEcho();
|
||||
}
|
||||
|
||||
private void clear() => AddStep("clear messages", textContainer.Clear);
|
||||
|
||||
private void addMessageWithChecks(string text, int linkAmount = 0, bool isAction = false, bool isImportant = false, params LinkAction[] expectedActions)
|
||||
[SetUp]
|
||||
public void Setup() => Schedule(() =>
|
||||
{
|
||||
int index = textContainer.Count + 1;
|
||||
var newLine = new ChatLine(new DummyMessage(text, isAction, isImportant, index));
|
||||
textContainer.Add(newLine);
|
||||
textContainer.Clear();
|
||||
});
|
||||
|
||||
AddAssert($"msg #{index} has {linkAmount} link(s)", () => newLine.Message.Links.Count == linkAmount);
|
||||
AddAssert($"msg #{index} has the right action", hasExpectedActions);
|
||||
//AddAssert($"msg #{index} is " + (isAction ? "italic" : "not italic"), () => newLine.ContentFlow.Any() && isAction == isItalic());
|
||||
AddAssert($"msg #{index} shows {linkAmount} link(s)", isShowingLinks);
|
||||
|
||||
bool hasExpectedActions()
|
||||
{
|
||||
var expectedActionsList = expectedActions.ToList();
|
||||
|
||||
if (expectedActionsList.Count != newLine.Message.Links.Count)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < newLine.Message.Links.Count; i++)
|
||||
{
|
||||
var action = newLine.Message.Links[i].Action;
|
||||
if (action != expectedActions[i]) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//bool isItalic() => newLine.ContentFlow.Where(d => d is OsuSpriteText).Cast<OsuSpriteText>().All(sprite => sprite.Font.Italics);
|
||||
|
||||
bool isShowingLinks()
|
||||
{
|
||||
bool hasBackground = !string.IsNullOrEmpty(newLine.Message.Sender.Colour);
|
||||
|
||||
Color4 textColour = isAction && hasBackground ? Color4Extensions.FromHex(newLine.Message.Sender.Colour) : Color4.White;
|
||||
|
||||
var linkCompilers = newLine.ContentFlow.Where(d => d is DrawableLinkCompiler).ToList();
|
||||
var linkSprites = linkCompilers.SelectMany(comp => ((DrawableLinkCompiler)comp).Parts);
|
||||
|
||||
return linkSprites.All(d => d.Colour == linkColour)
|
||||
&& newLine.ContentFlow.Except(linkSprites.Concat(linkCompilers)).All(d => d.Colour == textColour);
|
||||
}
|
||||
}
|
||||
|
||||
private void testLinksGeneral()
|
||||
[Test]
|
||||
public void TestLinksGeneral()
|
||||
{
|
||||
int messageIndex = 0;
|
||||
|
||||
addMessageWithChecks("test!");
|
||||
addMessageWithChecks("dev.ppy.sh!");
|
||||
addMessageWithChecks("https://dev.ppy.sh!", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("00:12:345 (1,2) - Test?", 1, expectedActions: LinkAction.OpenEditorTimestamp);
|
||||
addMessageWithChecks("Wiki link for tasty [[Performance Points]]", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("Wiki link for tasty [[Performance Points]]", 1, expectedActions: LinkAction.OpenWiki);
|
||||
addMessageWithChecks("(osu forums)[https://dev.ppy.sh/forum] (old link format)", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("[https://dev.ppy.sh/home New site] (new link format)", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("[osu forums](https://dev.ppy.sh/forum) (new link format 2)", 1, expectedActions: LinkAction.External);
|
||||
@ -117,7 +78,8 @@ namespace osu.Game.Tests.Visual.Online
|
||||
expectedActions: new[] { LinkAction.External, LinkAction.OpenBeatmap, LinkAction.External });
|
||||
addMessageWithChecks("[https://dev.ppy.sh/home New link format with escaped [and \\[ paired] braces]", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("[Markdown link format with escaped [and \\[ paired] braces](https://dev.ppy.sh/home)", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("(Old link format with escaped (and \\( paired) parentheses)[https://dev.ppy.sh/home] and [[also a rogue wiki link]]", 2, expectedActions: new[] { LinkAction.External, LinkAction.External });
|
||||
addMessageWithChecks("(Old link format with escaped (and \\( paired) parentheses)[https://dev.ppy.sh/home] and [[also a rogue wiki link]]", 2,
|
||||
expectedActions: new[] { LinkAction.External, LinkAction.OpenWiki });
|
||||
// note that there's 0 links here (they get removed if a channel is not found)
|
||||
addMessageWithChecks("#lobby or #osu would be blue (and work) in the ChatDisplay test (when a proper ChatOverlay is present).");
|
||||
addMessageWithChecks("I am important!", 0, false, true);
|
||||
@ -129,11 +91,60 @@ namespace osu.Game.Tests.Visual.Online
|
||||
addMessageWithChecks("Join my osu://chan/#english.", 1, expectedActions: LinkAction.OpenChannel);
|
||||
addMessageWithChecks("Join my #english or #japanese channels.", 2, expectedActions: new[] { LinkAction.OpenChannel, LinkAction.OpenChannel });
|
||||
addMessageWithChecks("Join my #english or #nonexistent #hashtag channels.", 1, expectedActions: LinkAction.OpenChannel);
|
||||
|
||||
void addMessageWithChecks(string text, int linkAmount = 0, bool isAction = false, bool isImportant = false, params LinkAction[] expectedActions)
|
||||
{
|
||||
ChatLine newLine = null;
|
||||
int index = messageIndex++;
|
||||
|
||||
AddStep("add message", () =>
|
||||
{
|
||||
newLine = new ChatLine(new DummyMessage(text, isAction, isImportant, index));
|
||||
textContainer.Add(newLine);
|
||||
});
|
||||
|
||||
AddAssert($"msg #{index} has {linkAmount} link(s)", () => newLine.Message.Links.Count == linkAmount);
|
||||
AddAssert($"msg #{index} has the right action", hasExpectedActions);
|
||||
//AddAssert($"msg #{index} is " + (isAction ? "italic" : "not italic"), () => newLine.ContentFlow.Any() && isAction == isItalic());
|
||||
AddAssert($"msg #{index} shows {linkAmount} link(s)", isShowingLinks);
|
||||
|
||||
bool hasExpectedActions()
|
||||
{
|
||||
var expectedActionsList = expectedActions.ToList();
|
||||
|
||||
if (expectedActionsList.Count != newLine.Message.Links.Count)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < newLine.Message.Links.Count; i++)
|
||||
{
|
||||
var action = newLine.Message.Links[i].Action;
|
||||
if (action != expectedActions[i]) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//bool isItalic() => newLine.ContentFlow.Where(d => d is OsuSpriteText).Cast<OsuSpriteText>().All(sprite => sprite.Font.Italics);
|
||||
|
||||
bool isShowingLinks()
|
||||
{
|
||||
bool hasBackground = !string.IsNullOrEmpty(newLine.Message.Sender.Colour);
|
||||
|
||||
Color4 textColour = isAction && hasBackground ? Color4Extensions.FromHex(newLine.Message.Sender.Colour) : Color4.White;
|
||||
|
||||
var linkCompilers = newLine.ContentFlow.Where(d => d is DrawableLinkCompiler).ToList();
|
||||
var linkSprites = linkCompilers.SelectMany(comp => ((DrawableLinkCompiler)comp).Parts);
|
||||
|
||||
return linkSprites.All(d => d.Colour == linkColour)
|
||||
&& newLine.ContentFlow.Except(linkSprites.Concat(linkCompilers)).All(d => d.Colour == textColour);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void testEcho()
|
||||
[Test]
|
||||
public void TestEcho()
|
||||
{
|
||||
int echoCounter = 0;
|
||||
int messageIndex = 0;
|
||||
|
||||
addEchoWithWait("sent!", "received!");
|
||||
addEchoWithWait("https://dev.ppy.sh/home", null, 500);
|
||||
@ -142,15 +153,16 @@ namespace osu.Game.Tests.Visual.Online
|
||||
|
||||
void addEchoWithWait(string text, string completeText = null, double delay = 250)
|
||||
{
|
||||
var newLine = new ChatLine(new DummyEchoMessage(text));
|
||||
int index = messageIndex++;
|
||||
|
||||
AddStep($"send msg #{++echoCounter} after {delay}ms", () =>
|
||||
AddStep($"send msg #{index} after {delay}ms", () =>
|
||||
{
|
||||
ChatLine newLine = new ChatLine(new DummyEchoMessage(text));
|
||||
textContainer.Add(newLine);
|
||||
Scheduler.AddDelayed(() => newLine.Message = new DummyMessage(completeText ?? text), delay);
|
||||
});
|
||||
|
||||
AddUntilStep($"wait for msg #{echoCounter}", () => textContainer.All(line => line.Message is DummyMessage));
|
||||
AddUntilStep($"wait for msg #{index}", () => textContainer.All(line => line.Message is DummyMessage));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,8 +93,12 @@ namespace osu.Game.Beatmaps
|
||||
if (t.Time > lastTime)
|
||||
return (beatLength: t.BeatLength, 0);
|
||||
|
||||
// osu-stable forced the first control point to start at 0.
|
||||
// This is reproduced here to maintain compatibility around osu!mania scroll speed and song select display.
|
||||
double currentTime = i == 0 ? 0 : t.Time;
|
||||
double nextTime = i == ControlPointInfo.TimingPoints.Count - 1 ? lastTime : ControlPointInfo.TimingPoints[i + 1].Time;
|
||||
return (beatLength: t.BeatLength, duration: nextTime - t.Time);
|
||||
|
||||
return (beatLength: t.BeatLength, duration: nextTime - currentTime);
|
||||
})
|
||||
// Aggregate durations into a set of (beatLength, duration) tuples for each beat length
|
||||
.GroupBy(t => Math.Round(t.beatLength * 1000) / 1000)
|
||||
|
@ -57,6 +57,7 @@ namespace osu.Game.Online.Chat
|
||||
/// </summary>
|
||||
public static string WebsiteRootUrl
|
||||
{
|
||||
get => websiteRootUrl;
|
||||
set => websiteRootUrl = value
|
||||
.Trim('/') // trim potential trailing slash/
|
||||
.Split('/').Last(); // only keep domain name, ignoring protocol.
|
||||
@ -134,7 +135,7 @@ namespace osu.Game.Online.Chat
|
||||
case "http":
|
||||
case "https":
|
||||
// length > 3 since all these links need another argument to work
|
||||
if (args.Length > 3 && args[1].EndsWith(websiteRootUrl, StringComparison.OrdinalIgnoreCase))
|
||||
if (args.Length > 3 && args[1].EndsWith(WebsiteRootUrl, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
string mainArg = args[3];
|
||||
|
||||
@ -262,7 +263,7 @@ namespace osu.Game.Online.Chat
|
||||
handleMatches(old_link_regex, "{1}", "{2}", result, startIndex, escapeChars: new[] { '(', ')' });
|
||||
|
||||
// handle wiki links
|
||||
handleMatches(wiki_regex, "{1}", "https://osu.ppy.sh/wiki/{1}", result, startIndex);
|
||||
handleMatches(wiki_regex, "{1}", $"https://{WebsiteRootUrl}/wiki/{{1}}", result, startIndex);
|
||||
|
||||
// handle bare links
|
||||
handleAdvanced(advanced_link_regex, result, startIndex);
|
||||
|
@ -36,7 +36,7 @@
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Realm" Version="10.7.1" />
|
||||
<PackageReference Include="ppy.osu.Framework" Version="2022.107.0" />
|
||||
<PackageReference Include="ppy.osu.Framework" Version="2022.111.0" />
|
||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2022.109.0" />
|
||||
<PackageReference Include="Sentry" Version="3.12.1" />
|
||||
<PackageReference Include="SharpCompress" Version="0.30.1" />
|
||||
|
@ -60,7 +60,7 @@
|
||||
<Reference Include="System.Net.Http" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Label="Package References">
|
||||
<PackageReference Include="ppy.osu.Framework.iOS" Version="2022.107.0" />
|
||||
<PackageReference Include="ppy.osu.Framework.iOS" Version="2022.111.0" />
|
||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2022.109.0" />
|
||||
</ItemGroup>
|
||||
<!-- See https://github.com/dotnet/runtime/issues/35988 (can be removed after Xamarin uses net5.0 / net6.0) -->
|
||||
@ -83,7 +83,7 @@
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="ppy.osu.Framework" Version="2022.107.0" />
|
||||
<PackageReference Include="ppy.osu.Framework" Version="2022.111.0" />
|
||||
<PackageReference Include="SharpCompress" Version="0.30.0" />
|
||||
<PackageReference Include="NUnit" Version="3.13.2" />
|
||||
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
||||
|
Loading…
Reference in New Issue
Block a user