Skip to content

Commit

Permalink
UI: Add descriptions of what each dynamic RPC formatter actually show…
Browse files Browse the repository at this point in the history
…s when hovering whether it has support in the game info popup
  • Loading branch information
GreemDev committed Feb 16, 2025
1 parent aa2178d commit 0d7d0e8
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 18 deletions.
14 changes: 10 additions & 4 deletions src/Ryujinx/UI/Controls/ApplicationDataView.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -119,17 +119,23 @@
TextWrapping="Wrap" >
</TextBlock>
</StackPanel>
<StackPanel Orientation="Horizontal" Spacing="5">
<ui:SymbolIcon Foreground="ForestGreen" Symbol="Checkmark" IsVisible="{Binding AppData.HasDynamicRichPresenceSupport}"/>
<StackPanel Orientation="Horizontal" Spacing="5" ToolTip.Tip="{Binding DynamicRichPresenceDescription}">
<ui:SymbolIcon
Foreground="ForestGreen"
Symbol="Checkmark"
IsVisible="{Binding AppData.HasDynamicRichPresenceSupport}"/>
<TextBlock
Foreground="ForestGreen"
HorizontalAlignment="Stretch"
IsVisible="{Binding AppData.HasDynamicRichPresenceSupport}"
Text="{ext:Locale GameInfoRpcDynamic}"
TextAlignment="Start"
TextWrapping="Wrap" >
TextWrapping="Wrap">
</TextBlock>
<ui:SymbolIcon Foreground="Red" Symbol="Cancel" IsVisible="{Binding !AppData.HasDynamicRichPresenceSupport}"/>
<ui:SymbolIcon
Foreground="Red"
Symbol="Cancel"
IsVisible="{Binding !AppData.HasDynamicRichPresenceSupport}"/>
<TextBlock
Foreground="Red"
HorizontalAlignment="Stretch"
Expand Down
6 changes: 6 additions & 0 deletions src/Ryujinx/UI/ViewModels/ApplicationDataViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Gommon;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Utilities.AppLibrary;
using Ryujinx.Ava.Utilities.PlayReport;

namespace Ryujinx.Ava.UI.ViewModels
{
Expand All @@ -10,6 +11,11 @@ public class ApplicationDataViewModel : BaseModel

public ApplicationDataViewModel(ApplicationData appData) => AppData = appData;

public string DynamicRichPresenceDescription =>
AppData.HasDynamicRichPresenceSupport
? AppData.RichPresenceSpec.Value.Description
: GameSpec.DefaultDescription;

public string FormattedVersion => LocaleManager.Instance[LocaleKeys.GameListHeaderVersion].Format(AppData.Version);
public string FormattedDeveloper => LocaleManager.Instance[LocaleKeys.GameListHeaderDeveloper].Format(AppData.Developer);
public string FormattedFileExtension => LocaleManager.Instance[LocaleKeys.GameListHeaderFileExtension].Format(AppData.FileExtension);
Expand Down
10 changes: 8 additions & 2 deletions src/Ryujinx/Utilities/AppLibrary/ApplicationData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using LibHac.Tools.FsSystem.NcaUtils;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Utilities.Compat;
using Ryujinx.Ava.Utilities.PlayReport;
using Ryujinx.Common.Logging;
using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.Loaders.Processes.Extensions;
Expand All @@ -35,9 +36,14 @@ public ulong Id
{
_id = value;

Compatibility = CompatibilityCsv.Find(Id);
Compatibility = CompatibilityCsv.Find(value);
RichPresenceSpec = PlayReports.Analyzer.TryGetSpec(IdString, out GameSpec gameSpec)
? gameSpec
: default(Optional<GameSpec>);
}
}
public Optional<GameSpec> RichPresenceSpec { get; set; }

public string Developer { get; set; } = "Unknown";
public string Version { get; set; } = "0";
public int PlayerCount { get; set; }
Expand All @@ -46,7 +52,7 @@ public ulong Id
public bool HasLdnGames => PlayerCount != 0 && GameCount != 0;

public bool HasRichPresenceAsset => DiscordIntegrationModule.HasAssetImage(IdString);
public bool HasDynamicRichPresenceSupport => DiscordIntegrationModule.HasAnalyzer(IdString);
public bool HasDynamicRichPresenceSupport => RichPresenceSpec.HasValue;

public TimeSpan TimePlayed { get; set; }
public DateTime? LastPlayed { get; set; }
Expand Down
11 changes: 8 additions & 3 deletions src/Ryujinx/Utilities/PlayReport/Analyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ public class Analyzer

public IReadOnlyList<GameSpec> Specs => new ReadOnlyCollection<GameSpec>(_specs);

public GameSpec GetSpec(string titleId) => _specs.First(x => x.TitleIds.ContainsIgnoreCase(titleId));

public bool TryGetSpec(string titleId, out GameSpec gameSpec)
=> (gameSpec = _specs.FirstOrDefault(x => x.TitleIds.ContainsIgnoreCase(titleId))) != null;

/// <summary>
/// Add an analysis spec matching a specific game by title ID, with the provided spec configuration.
/// </summary>
Expand Down Expand Up @@ -128,13 +133,13 @@ Horizon.Prepo.Types.PlayReport playReport
{
if (!playReport.ReportData.IsDictionary)
return FormattedValue.Unhandled;

if (!_specs.TryGetFirst(s => runningGameId.EqualsAnyIgnoreCase(s.TitleIds), out GameSpec spec))
if (!TryGetSpec(runningGameId, out GameSpec spec))
return FormattedValue.Unhandled;

foreach (FormatterSpecBase formatSpec in spec.ValueFormatters.OrderBy(x => x.Priority))
{
if (!formatSpec.Format(appMeta, playReport, out FormattedValue value))
if (!formatSpec.TryFormat(appMeta, playReport, out FormattedValue value))
continue;

return value;
Expand Down
32 changes: 24 additions & 8 deletions src/Ryujinx/Utilities/PlayReport/PlayReports.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,41 +17,56 @@ public static void Initialize()
.AddSpec(
"01007ef00011e000",
spec => spec
.WithDescription("based on being in Master Mode.")
.AddValueFormatter("IsHardMode", BreathOfTheWild_MasterMode)
// reset to normal status when switching between normal & master mode in title screen
.AddValueFormatter("AoCVer", FormattedValue.SingleAlwaysResets)
)
.AddSpec(
"0100f2c0115b6000",
spec => spec
.WithDescription("based on where you are in Hyrule (Depths, Surface, Sky).")
.AddValueFormatter("PlayerPosY", TearsOfTheKingdom_CurrentField))
.AddSpec(
"01002da013484000",
spec => spec
.WithDescription("based on how many Rupees you have.")
.AddValueFormatter("rupees", SkywardSwordHD_Rupees))
.AddSpec(
"0100000000010000",
spec =>
spec.AddValueFormatter("is_kids_mode", SuperMarioOdyssey_AssistMode)
spec => spec
.WithDescription("based on if you're playing with Assist Mode.")
.AddValueFormatter("is_kids_mode", SuperMarioOdyssey_AssistMode)
)
.AddSpec(
"010075000ecbe000",
spec =>
spec.AddValueFormatter("is_kids_mode", SuperMarioOdysseyChina_AssistMode)
spec => spec
.WithDescription("based on if you're playing with Assist Mode.")
.AddValueFormatter("is_kids_mode", SuperMarioOdysseyChina_AssistMode)
)
.AddSpec(
"010028600ebda000",
spec => spec.AddValueFormatter("mode", SuperMario3DWorldOrBowsersFury)
spec => spec
.WithDescription("based on being in either Super Mario 3D World or Bowser's Fury.")
.AddValueFormatter("mode", SuperMario3DWorldOrBowsersFury)
)
.AddSpec( // Global & China IDs
["0100152000022000", "010075100e8ec000"],
spec => spec.AddValueFormatter("To", MarioKart8Deluxe_Mode)
spec => spec
.WithDescription("based on what modes you're selecting in the menu & whether or not you're in a race.")
.AddValueFormatter("To", MarioKart8Deluxe_Mode)
)
.AddSpec(
["0100a3d008c5c000", "01008f6008c5e000"],
spec => spec
.WithDescription("based on what area of Paldea you're exploring.")
.AddValueFormatter("area_no", PokemonSVArea)
.AddValueFormatter("team_circle", PokemonSVUnionCircle)
)
.AddSpec(
"01006a800016e000",
spec => spec
.WithDescription("based on what mode you're playing, who won, and what characters were present.")
.AddSparseMultiValueFormatter(
[
// Metadata to figure out what PlayReport we have.
Expand All @@ -72,9 +87,10 @@ public static void Initialize()
"0100c9a00ece6000", "01008d300c50c000", "0100d870045b6000",
"010012f017576000", "0100c62011050000", "0100b3c014bda000"
],
spec => spec.AddValueFormatter("launch_title_id", NsoEmulator_LaunchedGame)
spec => spec
.WithDescription("based on what game you first launch.\n\nNSO emulators do not print any Play Report information past the first game launch so it's all we got.")
.AddValueFormatter("launch_title_id", NsoEmulator_LaunchedGame)
)
.AddSpec("01002da013484000", spec => spec.AddValueFormatter("rupees", SkywardSwordHD_Rupees))
);

private static string Playing(string game) => $"Playing {game}";
Expand Down
16 changes: 15 additions & 1 deletion src/Ryujinx/Utilities/PlayReport/Specs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,20 @@ public static GameSpec Create(IEnumerable<string> titleIds)

public required string[] TitleIds { get; init; }

public const string DefaultDescription = "Formats the details on your Discord presence based on logged data from the game.";

private string _valueDescription;

public string Description => _valueDescription ?? DefaultDescription;

public GameSpec WithDescription(string description)
{
_valueDescription = description != null
? $"Formats the details on your Discord presence {description}"
: null;
return this;
}

public List<FormatterSpecBase> ValueFormatters { get; } = [];


Expand Down Expand Up @@ -197,7 +211,7 @@ public abstract class FormatterSpecBase
public string[] ReportKeys { get; init; }
public Delegate Formatter { get; init; }

public bool Format(ApplicationMetadata appMeta, Horizon.Prepo.Types.PlayReport playReport,
public bool TryFormat(ApplicationMetadata appMeta, Horizon.Prepo.Types.PlayReport playReport,
out FormattedValue formattedValue)
{
formattedValue = default;
Expand Down

0 comments on commit 0d7d0e8

Please sign in to comment.