1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-15 04:13:00 +08:00

Merge pull request #21420 from cdwcgt/NowPlaying

Show mods, ruleset and unicode metadata in "now playing" chat command
This commit is contained in:
Dean Herbert 2022-11-30 15:57:52 +09:00 committed by GitHub
commit 78f70dae75
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 84 additions and 13 deletions

View File

@ -11,6 +11,7 @@ using osu.Game.Beatmaps;
using osu.Game.Online.API;
using osu.Game.Online.Chat;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods;
using osu.Game.Users;
namespace osu.Game.Tests.Visual.Online
@ -33,7 +34,7 @@ namespace osu.Game.Tests.Visual.Online
{
AddStep("Set activity", () => api.Activity.Value = new UserActivity.InLobby(null));
AddStep("Run command", () => Add(new NowPlayingCommand()));
AddStep("Run command", () => Add(new NowPlayingCommand(new Channel())));
AddAssert("Check correct response", () => postTarget.LastMessage.Contains("is listening"));
}
@ -43,7 +44,7 @@ namespace osu.Game.Tests.Visual.Online
{
AddStep("Set activity", () => api.Activity.Value = new UserActivity.Editing(new BeatmapInfo()));
AddStep("Run command", () => Add(new NowPlayingCommand()));
AddStep("Run command", () => Add(new NowPlayingCommand(new Channel())));
AddAssert("Check correct response", () => postTarget.LastMessage.Contains("is editing"));
}
@ -53,7 +54,7 @@ namespace osu.Game.Tests.Visual.Online
{
AddStep("Set activity", () => api.Activity.Value = new UserActivity.InSoloGame(new BeatmapInfo(), new RulesetInfo()));
AddStep("Run command", () => Add(new NowPlayingCommand()));
AddStep("Run command", () => Add(new NowPlayingCommand(new Channel())));
AddAssert("Check correct response", () => postTarget.LastMessage.Contains("is playing"));
}
@ -69,7 +70,7 @@ namespace osu.Game.Tests.Visual.Online
BeatmapInfo = { OnlineID = hasOnlineId ? 1234 : -1 }
});
AddStep("Run command", () => Add(new NowPlayingCommand()));
AddStep("Run command", () => Add(new NowPlayingCommand(new Channel())));
if (hasOnlineId)
AddAssert("Check link presence", () => postTarget.LastMessage.Contains("/b/1234"));
@ -77,6 +78,18 @@ namespace osu.Game.Tests.Visual.Online
AddAssert("Check link not present", () => !postTarget.LastMessage.Contains("https://"));
}
[Test]
public void TestModPresence()
{
AddStep("Set activity", () => api.Activity.Value = new UserActivity.InSoloGame(new BeatmapInfo(), new RulesetInfo()));
AddStep("Add Hidden mod", () => SelectedMods.Value = new[] { Ruleset.Value.CreateInstance().CreateMod<ModHidden>() });
AddStep("Run command", () => Add(new NowPlayingCommand(new Channel())));
AddAssert("Check mod is present", () => postTarget.LastMessage.Contains("+HD"));
}
public partial class PostTarget : Component, IChannelPostTarget
{
public void PostMessage(string text, bool isAction = false, Channel target = null)

View File

@ -1,13 +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.
#nullable disable
using System.Collections.Generic;
using System.Linq;
using System.Text;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Localisation;
using osu.Game.Beatmaps;
using osu.Game.Online.API;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods;
using osu.Game.Users;
namespace osu.Game.Online.Chat
@ -15,21 +19,30 @@ namespace osu.Game.Online.Chat
public partial class NowPlayingCommand : Component
{
[Resolved]
private IChannelPostTarget channelManager { get; set; }
private IChannelPostTarget channelManager { get; set; } = null!;
[Resolved]
private IAPIProvider api { get; set; }
private IAPIProvider api { get; set; } = null!;
[Resolved]
private Bindable<WorkingBeatmap> currentBeatmap { get; set; }
private Bindable<WorkingBeatmap> currentBeatmap { get; set; } = null!;
private readonly Channel target;
[Resolved]
private Bindable<IReadOnlyList<Mod>> selectedMods { get; set; } = null!;
[Resolved]
private IBindable<RulesetInfo> currentRuleset { get; set; } = null!;
[Resolved]
private LocalisationManager localisation { get; set; } = null!;
private readonly Channel? target;
/// <summary>
/// Creates a new <see cref="NowPlayingCommand"/> to post the currently-playing beatmap to a parenting <see cref="IChannelPostTarget"/>.
/// </summary>
/// <param name="target">The target channel to post to. If <c>null</c>, the currently-selected channel will be posted to.</param>
public NowPlayingCommand(Channel target = null)
public NowPlayingCommand(Channel target)
{
this.target = target;
}
@ -59,10 +72,55 @@ namespace osu.Game.Online.Chat
break;
}
string beatmapString = beatmapInfo.OnlineID > 0 ? $"[{api.WebsiteRootUrl}/b/{beatmapInfo.OnlineID} {beatmapInfo}]" : beatmapInfo.ToString();
string[] pieces =
{
"is",
verb,
getBeatmapPart(),
getRulesetPart(),
getModPart(),
};
channelManager.PostMessage($"is {verb} {beatmapString}", true, target);
channelManager.PostMessage(string.Join(' ', pieces.Where(p => !string.IsNullOrEmpty(p))), true, target);
Expire();
string getBeatmapPart()
{
string beatmapInfoString = localisation.GetLocalisedBindableString(beatmapInfo.GetDisplayTitleRomanisable()).Value;
return beatmapInfo.OnlineID > 0 ? $"[{api.WebsiteRootUrl}/b/{beatmapInfo.OnlineID} {beatmapInfoString}]" : beatmapInfoString;
}
string getRulesetPart()
{
if (api.Activity.Value is not UserActivity.InGame) return string.Empty;
return $"<{currentRuleset.Value.Name}>";
}
string getModPart()
{
if (api.Activity.Value is not UserActivity.InGame) return string.Empty;
if (selectedMods.Value.Count == 0)
{
return string.Empty;
}
StringBuilder modsString = new StringBuilder();
foreach (var mod in selectedMods.Value.Where(mod => mod.Type == ModType.DifficultyIncrease))
{
modsString.Append($"+{mod.Acronym} ");
}
foreach (var mod in selectedMods.Value.Where(mod => mod.Type != ModType.DifficultyIncrease))
{
modsString.Append($"-{mod.Acronym} ");
}
return modsString.ToString().Trim();
}
}
}
}