UI: The argument to Play Report value formatters is now a struct containing the current ApplicationMetadata & the BoxedValue that was the only argument previously.
This allows for the title of Mario Kart to be localized when one of the value checkers doesn't match.metal Canary-1.2.329
parent
8117e160c2
commit
fe43c32e60
|
|
@ -1,80 +0,0 @@
|
||||||
using Gommon;
|
|
||||||
using MsgPack;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Ryujinx.Common.Helper
|
|
||||||
{
|
|
||||||
public class PlayReportAnalyzer
|
|
||||||
{
|
|
||||||
private readonly List<PlayReportGameSpec> _specs = [];
|
|
||||||
|
|
||||||
public PlayReportAnalyzer AddSpec(string titleId, Func<PlayReportGameSpec, PlayReportGameSpec> transform)
|
|
||||||
{
|
|
||||||
_specs.Add(transform(new PlayReportGameSpec { TitleIdStr = titleId }));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PlayReportAnalyzer AddSpec(string titleId, Action<PlayReportGameSpec> transform)
|
|
||||||
{
|
|
||||||
_specs.Add(new PlayReportGameSpec { TitleIdStr = titleId }.Apply(transform));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Optional<string> Run(string runningGameId, MessagePackObject playReport)
|
|
||||||
{
|
|
||||||
if (!playReport.IsDictionary)
|
|
||||||
return Optional<string>.None;
|
|
||||||
|
|
||||||
if (!_specs.TryGetFirst(s => s.TitleIdStr.EqualsIgnoreCase(runningGameId), out PlayReportGameSpec spec))
|
|
||||||
return Optional<string>.None;
|
|
||||||
|
|
||||||
foreach (PlayReportValueFormatterSpec formatSpec in spec.Analyses.OrderBy(x => x.Priority))
|
|
||||||
{
|
|
||||||
if (!playReport.AsDictionary().TryGetValue(formatSpec.ReportKey, out MessagePackObject valuePackObject))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
return formatSpec.ValueFormatter(valuePackObject.ToObject());
|
|
||||||
}
|
|
||||||
|
|
||||||
return Optional<string>.None;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public class PlayReportGameSpec
|
|
||||||
{
|
|
||||||
public required string TitleIdStr { get; init; }
|
|
||||||
public List<PlayReportValueFormatterSpec> Analyses { get; } = [];
|
|
||||||
|
|
||||||
public PlayReportGameSpec AddValueFormatter(string reportKey, Func<object, string> valueFormatter)
|
|
||||||
{
|
|
||||||
Analyses.Add(new PlayReportValueFormatterSpec
|
|
||||||
{
|
|
||||||
Priority = Analyses.Count,
|
|
||||||
ReportKey = reportKey,
|
|
||||||
ValueFormatter = valueFormatter
|
|
||||||
});
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PlayReportGameSpec AddValueFormatter(int priority, string reportKey, Func<object, string> valueFormatter)
|
|
||||||
{
|
|
||||||
Analyses.Add(new PlayReportValueFormatterSpec
|
|
||||||
{
|
|
||||||
Priority = priority,
|
|
||||||
ReportKey = reportKey,
|
|
||||||
ValueFormatter = valueFormatter
|
|
||||||
});
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct PlayReportValueFormatterSpec
|
|
||||||
{
|
|
||||||
public required int Priority { get; init; }
|
|
||||||
public required string ReportKey { get; init; }
|
|
||||||
public required Func<object, string> ValueFormatter { get; init; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -39,6 +39,7 @@ namespace Ryujinx.Ava
|
||||||
private static DiscordRpcClient _discordClient;
|
private static DiscordRpcClient _discordClient;
|
||||||
private static RichPresence _discordPresenceMain;
|
private static RichPresence _discordPresenceMain;
|
||||||
private static RichPresence _discordPresencePlaying;
|
private static RichPresence _discordPresencePlaying;
|
||||||
|
private static ApplicationMetadata _currentApp;
|
||||||
|
|
||||||
public static void Initialize()
|
public static void Initialize()
|
||||||
{
|
{
|
||||||
|
|
@ -113,6 +114,7 @@ namespace Ryujinx.Ava
|
||||||
private static void SwitchToPlayingState(ApplicationMetadata appMeta, ProcessResult procRes)
|
private static void SwitchToPlayingState(ApplicationMetadata appMeta, ProcessResult procRes)
|
||||||
{
|
{
|
||||||
_discordClient?.SetPresence(_discordPresencePlaying ??= CreatePlayingState(appMeta, procRes));
|
_discordClient?.SetPresence(_discordPresencePlaying ??= CreatePlayingState(appMeta, procRes));
|
||||||
|
_currentApp = appMeta;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void UpdatePlayingState()
|
private static void UpdatePlayingState()
|
||||||
|
|
@ -124,6 +126,7 @@ namespace Ryujinx.Ava
|
||||||
{
|
{
|
||||||
_discordClient?.SetPresence(_discordPresenceMain);
|
_discordClient?.SetPresence(_discordPresenceMain);
|
||||||
_discordPresencePlaying = null;
|
_discordPresencePlaying = null;
|
||||||
|
_currentApp = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void HandlePlayReport(MessagePackObject playReport)
|
private static void HandlePlayReport(MessagePackObject playReport)
|
||||||
|
|
@ -131,7 +134,7 @@ namespace Ryujinx.Ava
|
||||||
if (!TitleIDs.CurrentApplication.Value.HasValue) return;
|
if (!TitleIDs.CurrentApplication.Value.HasValue) return;
|
||||||
if (_discordPresencePlaying is null) return;
|
if (_discordPresencePlaying is null) return;
|
||||||
|
|
||||||
Optional<string> details = PlayReport.Analyzer.Run(TitleIDs.CurrentApplication.Value, playReport);
|
Optional<string> details = PlayReport.Analyzer.Run(TitleIDs.CurrentApplication.Value, _currentApp, playReport);
|
||||||
|
|
||||||
if (!details.HasValue) return;
|
if (!details.HasValue) return;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,10 @@
|
||||||
using Ryujinx.Common.Helper;
|
using Gommon;
|
||||||
|
using MsgPack;
|
||||||
|
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||||
|
using Ryujinx.Common.Helper;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.Utilities
|
namespace Ryujinx.Ava.Utilities
|
||||||
{
|
{
|
||||||
|
|
@ -32,20 +38,20 @@ namespace Ryujinx.Ava.Utilities
|
||||||
spec => spec.AddValueFormatter("To", MarioKart8Deluxe_Mode)
|
spec => spec.AddValueFormatter("To", MarioKart8Deluxe_Mode)
|
||||||
);
|
);
|
||||||
|
|
||||||
private static string BreathOfTheWild_MasterMode(object val)
|
private static string BreathOfTheWild_MasterMode(ref PlayReportValue value)
|
||||||
=> val is 1 ? "Playing Master Mode" : "Playing Normal Mode";
|
=> value.BoxedValue is 1 ? "Playing Master Mode" : "Playing Normal Mode";
|
||||||
|
|
||||||
private static string SuperMarioOdyssey_AssistMode(object val)
|
private static string SuperMarioOdyssey_AssistMode(ref PlayReportValue value)
|
||||||
=> val is 1 ? "Playing in Assist Mode" : "Playing in Regular Mode";
|
=> value.BoxedValue is 1 ? "Playing in Assist Mode" : "Playing in Regular Mode";
|
||||||
|
|
||||||
private static string SuperMarioOdysseyChina_AssistMode(object val)
|
private static string SuperMarioOdysseyChina_AssistMode(ref PlayReportValue value)
|
||||||
=> val is 1 ? "Playing in 帮助模式" : "Playing in 普通模式";
|
=> value.BoxedValue is 1 ? "Playing in 帮助模式" : "Playing in 普通模式";
|
||||||
|
|
||||||
private static string SuperMario3DWorldOrBowsersFury(object val)
|
private static string SuperMario3DWorldOrBowsersFury(ref PlayReportValue value)
|
||||||
=> val is 0 ? "Playing Super Mario 3D World" : "Playing Bowser's Fury";
|
=> value.BoxedValue is 0 ? "Playing Super Mario 3D World" : "Playing Bowser's Fury";
|
||||||
|
|
||||||
private static string MarioKart8Deluxe_Mode(object obj)
|
private static string MarioKart8Deluxe_Mode(ref PlayReportValue value)
|
||||||
=> obj switch
|
=> value.BoxedValue switch
|
||||||
{
|
{
|
||||||
// Single Player
|
// Single Player
|
||||||
"Single" => "Single Player",
|
"Single" => "Single Player",
|
||||||
|
|
@ -69,8 +75,97 @@ namespace Ryujinx.Ava.Utilities
|
||||||
"Battle" => "Battle Mode",
|
"Battle" => "Battle Mode",
|
||||||
"RaceStart" => "Selecting a Course",
|
"RaceStart" => "Selecting a Course",
|
||||||
"Race" => "Racing",
|
"Race" => "Racing",
|
||||||
//TODO: refactor value formatting system to pass in the name from the content archive so this can be localized properly
|
_ => $"Playing {value.Application.Title}"
|
||||||
_ => "Playing Mario Kart 8 Deluxe"
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region Analyzer implementation
|
||||||
|
|
||||||
|
public class PlayReportAnalyzer
|
||||||
|
{
|
||||||
|
private readonly List<PlayReportGameSpec> _specs = [];
|
||||||
|
|
||||||
|
public PlayReportAnalyzer AddSpec(string titleId, Func<PlayReportGameSpec, PlayReportGameSpec> transform)
|
||||||
|
{
|
||||||
|
_specs.Add(transform(new PlayReportGameSpec { TitleIdStr = titleId }));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PlayReportAnalyzer AddSpec(string titleId, Action<PlayReportGameSpec> transform)
|
||||||
|
{
|
||||||
|
_specs.Add(new PlayReportGameSpec { TitleIdStr = titleId }.Apply(transform));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<string> Run(string runningGameId, ApplicationMetadata appMeta, MessagePackObject playReport)
|
||||||
|
{
|
||||||
|
if (!playReport.IsDictionary)
|
||||||
|
return Optional<string>.None;
|
||||||
|
|
||||||
|
if (!_specs.TryGetFirst(s => s.TitleIdStr.EqualsIgnoreCase(runningGameId), out PlayReportGameSpec spec))
|
||||||
|
return Optional<string>.None;
|
||||||
|
|
||||||
|
foreach (PlayReportValueFormatterSpec formatSpec in spec.Analyses.OrderBy(x => x.Priority))
|
||||||
|
{
|
||||||
|
if (!playReport.AsDictionary().TryGetValue(formatSpec.ReportKey, out MessagePackObject valuePackObject))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
PlayReportValue value = new()
|
||||||
|
{
|
||||||
|
Application = appMeta,
|
||||||
|
BoxedValue = valuePackObject.ToObject()
|
||||||
|
};
|
||||||
|
|
||||||
|
return formatSpec.ValueFormatter(ref value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Optional<string>.None;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PlayReportGameSpec
|
||||||
|
{
|
||||||
|
public required string TitleIdStr { get; init; }
|
||||||
|
public List<PlayReportValueFormatterSpec> Analyses { get; } = [];
|
||||||
|
|
||||||
|
public PlayReportGameSpec AddValueFormatter(string reportKey, PlayReportValueFormatter valueFormatter)
|
||||||
|
{
|
||||||
|
Analyses.Add(new PlayReportValueFormatterSpec
|
||||||
|
{
|
||||||
|
Priority = Analyses.Count,
|
||||||
|
ReportKey = reportKey,
|
||||||
|
ValueFormatter = valueFormatter
|
||||||
|
});
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PlayReportGameSpec AddValueFormatter(int priority, string reportKey, PlayReportValueFormatter valueFormatter)
|
||||||
|
{
|
||||||
|
Analyses.Add(new PlayReportValueFormatterSpec
|
||||||
|
{
|
||||||
|
Priority = priority,
|
||||||
|
ReportKey = reportKey,
|
||||||
|
ValueFormatter = valueFormatter
|
||||||
|
});
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct PlayReportValue
|
||||||
|
{
|
||||||
|
public ApplicationMetadata Application { get; init; }
|
||||||
|
public object BoxedValue { get; init; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct PlayReportValueFormatterSpec
|
||||||
|
{
|
||||||
|
public required int Priority { get; init; }
|
||||||
|
public required string ReportKey { get; init; }
|
||||||
|
public required PlayReportValueFormatter ValueFormatter { get; init; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public delegate string PlayReportValueFormatter(ref PlayReportValue value);
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue