Compare commits
2 Commits
Canary-1.2
...
Canary-1.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2d7700949c | ||
|
|
ea2287af03 |
80
src/Ryujinx.Common/Helpers/PlayReportAnalyzer.cs
Normal file
80
src/Ryujinx.Common/Helpers/PlayReportAnalyzer.cs
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
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; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,7 +7,7 @@ namespace Ryujinx.Horizon
|
|||||||
{
|
{
|
||||||
public static class HorizonStatic
|
public static class HorizonStatic
|
||||||
{
|
{
|
||||||
internal static void HandlePlayReport(MessagePackObject report) => PlayReportPrinted.Invoke(report);
|
internal static void HandlePlayReport(MessagePackObject report) => PlayReportPrinted?.Invoke(report);
|
||||||
|
|
||||||
public static event Action<MessagePackObject> PlayReportPrinted;
|
public static event Action<MessagePackObject> PlayReportPrinted;
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using Ryujinx.Ava.Utilities;
|
|||||||
using Ryujinx.Ava.Utilities.AppLibrary;
|
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||||
using Ryujinx.Ava.Utilities.Configuration;
|
using Ryujinx.Ava.Utilities.Configuration;
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
|
using Ryujinx.Common.Helper;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.HLE;
|
using Ryujinx.HLE;
|
||||||
using Ryujinx.HLE.Loaders.Processes;
|
using Ryujinx.HLE.Loaders.Processes;
|
||||||
@@ -45,8 +46,7 @@ namespace Ryujinx.Ava
|
|||||||
{
|
{
|
||||||
Assets = new Assets
|
Assets = new Assets
|
||||||
{
|
{
|
||||||
LargeImageKey = "ryujinx",
|
LargeImageKey = "ryujinx", LargeImageText = TruncateToByteLength(_description)
|
||||||
LargeImageText = TruncateToByteLength(_description)
|
|
||||||
},
|
},
|
||||||
Details = "Main Menu",
|
Details = "Main Menu",
|
||||||
State = "Idling",
|
State = "Idling",
|
||||||
@@ -126,37 +126,27 @@ namespace Ryujinx.Ava
|
|||||||
_discordPresencePlaying = null;
|
_discordPresencePlaying = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static readonly PlayReportAnalyzer _playReportAnalyzer = new PlayReportAnalyzer()
|
||||||
|
.AddSpec( // Breath of the Wild
|
||||||
|
"01007ef00011e000",
|
||||||
|
gameSpec =>
|
||||||
|
gameSpec.AddValueFormatter("IsHardMode", val => val is 1 ? "Playing Master Mode" : "Playing Normal Mode")
|
||||||
|
);
|
||||||
|
|
||||||
private static void HandlePlayReport(MessagePackObject playReport)
|
private static void HandlePlayReport(MessagePackObject playReport)
|
||||||
{
|
{
|
||||||
if (!TitleIDs.CurrentApplication.Value.HasValue) return;
|
if (!TitleIDs.CurrentApplication.Value.HasValue) return;
|
||||||
if (_discordPresencePlaying is null) return;
|
if (_discordPresencePlaying is null) return;
|
||||||
if (!playReport.IsDictionary) return;
|
|
||||||
|
|
||||||
_playReportValues
|
Optional<string> details = _playReportAnalyzer.Run(TitleIDs.CurrentApplication.Value, playReport);
|
||||||
.FindFirst(x => x.Key.EqualsIgnoreCase(TitleIDs.CurrentApplication.Value))
|
|
||||||
.Convert(x => x.Value)
|
|
||||||
.IfPresent(x =>
|
|
||||||
{
|
|
||||||
if (!playReport.AsDictionary().TryGetValue(x.ReportKey, out MessagePackObject valuePackObject))
|
|
||||||
return;
|
|
||||||
|
|
||||||
_discordPresencePlaying.Details = x.Formatter(valuePackObject.ToObject());
|
if (!details.HasValue) return;
|
||||||
|
|
||||||
|
_discordPresencePlaying.Details = details;
|
||||||
UpdatePlayingState();
|
UpdatePlayingState();
|
||||||
Logger.Info?.Print(LogClass.UI, "Updated Discord RPC based on a supported play report.");
|
Logger.Info?.Print(LogClass.UI, "Updated Discord RPC based on a supported play report.");
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// title ID -> Play Report key & value formatter
|
|
||||||
private static readonly ReadOnlyDictionary<string, (string ReportKey, Func<object, string> Formatter)>
|
|
||||||
_playReportValues = new(new Dictionary<string, (string ReportKey, Func<object, string> Formatter)>
|
|
||||||
{
|
|
||||||
{
|
|
||||||
// Breath of the Wild Master Mode display
|
|
||||||
"01007ef00011e000",
|
|
||||||
("IsHardMode", val => val is 1 ? "Playing Master Mode" : "Playing Normal Mode")
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
private static string TruncateToByteLength(string input)
|
private static string TruncateToByteLength(string input)
|
||||||
{
|
{
|
||||||
if (Encoding.UTF8.GetByteCount(input) <= ApplicationByteLimit)
|
if (Encoding.UTF8.GetByteCount(input) <= ApplicationByteLimit)
|
||||||
|
|||||||
Reference in New Issue
Block a user