From 131fe712053a78b99528d4492aba21e12b526689 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hack=E8=8C=B6=E3=82=93?= <120134269+Hackjjang@users.noreply.github.com> Date: Wed, 5 Feb 2025 17:40:37 +0900 Subject: [PATCH 1/6] Update Korean translation (#624) --- src/Ryujinx/Assets/locales.json | 44 ++++++++++++++++----------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/Ryujinx/Assets/locales.json b/src/Ryujinx/Assets/locales.json index d591d395f..8cf5b0d7c 100644 --- a/src/Ryujinx/Assets/locales.json +++ b/src/Ryujinx/Assets/locales.json @@ -584,7 +584,7 @@ "he_IL": "", "it_IT": "", "ja_JP": "", - "ko_KR": "", + "ko_KR": "UI를 숨긴 상태에서 게임 시작", "no_NO": "", "pl_PL": "", "pt_BR": "", @@ -2259,7 +2259,7 @@ "he_IL": "", "it_IT": "", "ja_JP": "", - "ko_KR": "", + "ko_KR": "PPTC 캐시 제거", "no_NO": "", "pl_PL": "", "pt_BR": "", @@ -2284,7 +2284,7 @@ "he_IL": "", "it_IT": "", "ja_JP": "", - "ko_KR": "", + "ko_KR": "앱의 모든 PPTC 캐시 파일 삭제", "no_NO": "", "pl_PL": "", "pt_BR": "", @@ -2609,7 +2609,7 @@ "he_IL": "", "it_IT": "", "ja_JP": "", - "ko_KR": "", + "ko_KR": "선택한 DLC 파일에서 RomFS 추출", "no_NO": "Pakk ut RomFS filene fra valgt DLC fil", "pl_PL": "", "pt_BR": "", @@ -2759,7 +2759,7 @@ "he_IL": "", "it_IT": "", "ja_JP": "", - "ko_KR": "", + "ko_KR": "호환성 항목 표시", "no_NO": "", "pl_PL": "", "pt_BR": "", @@ -2784,7 +2784,7 @@ "he_IL": "", "it_IT": "", "ja_JP": "", - "ko_KR": "", + "ko_KR": "일반적으로 도움말 메뉴를 통해 접근할 수 있는 호환성 목록에 선택한 게임을 표시합니다.", "no_NO": "", "pl_PL": "", "pt_BR": "", @@ -2809,7 +2809,7 @@ "he_IL": "", "it_IT": "", "ja_JP": "", - "ko_KR": "", + "ko_KR": "게임 통계 표시", "no_NO": "", "pl_PL": "", "pt_BR": "", @@ -2834,7 +2834,7 @@ "he_IL": "", "it_IT": "", "ja_JP": "", - "ko_KR": "", + "ko_KR": "그리드 보기 레이아웃에서 누락된 현재 선택된 게임에 대한 다양한 정보를 표시합니다.", "no_NO": "", "pl_PL": "", "pt_BR": "", @@ -3609,7 +3609,7 @@ "he_IL": "", "it_IT": "Aggiornamenti e DLC che fanno riferimento a file mancanti verranno disabilitati automaticamente", "ja_JP": "", - "ko_KR": "누락된 파일을 참조하는 DLC 및 업데이트가 자동으로 언로드", + "ko_KR": "누락된 파일을 참조하는 DLC 및 업데이트가 자동으로 불러오기 취소", "no_NO": "DLC og oppdateringer som henviser til manglende filer, vil bli lastet ned automatisk", "pl_PL": "", "pt_BR": "DLCs e Atualizações que se referem a arquivos ausentes serão descarregadas automaticamente", @@ -4384,7 +4384,7 @@ "he_IL": "", "it_IT": "", "ja_JP": "", - "ko_KR": "", + "ko_KR": "스웨덴어", "no_NO": "", "pl_PL": "", "pt_BR": "", @@ -4409,7 +4409,7 @@ "he_IL": "", "it_IT": "", "ja_JP": "", - "ko_KR": "", + "ko_KR": "노르웨이어", "no_NO": "Norsk", "pl_PL": "", "pt_BR": "", @@ -4484,7 +4484,7 @@ "he_IL": "", "it_IT": "", "ja_JP": "", - "ko_KR": "", + "ko_KR": "매치 시스템 시간", "no_NO": "", "pl_PL": "", "pt_BR": "", @@ -8084,7 +8084,7 @@ "he_IL": "", "it_IT": "", "ja_JP": "", - "ko_KR": "", + "ko_KR": "비활성화", "no_NO": "", "pl_PL": "", "pt_BR": "", @@ -8109,7 +8109,7 @@ "he_IL": "", "it_IT": "", "ja_JP": "", - "ko_KR": "", + "ko_KR": "레인보우", "no_NO": "", "pl_PL": "", "pt_BR": "", @@ -8134,7 +8134,7 @@ "he_IL": "", "it_IT": "", "ja_JP": "", - "ko_KR": "", + "ko_KR": "레인보우 속도", "no_NO": "", "pl_PL": "", "pt_BR": "", @@ -8159,7 +8159,7 @@ "he_IL": "", "it_IT": "", "ja_JP": "", - "ko_KR": "", + "ko_KR": "색상", "no_NO": "", "pl_PL": "", "pt_BR": "", @@ -13409,7 +13409,7 @@ "he_IL": "", "it_IT": "", "ja_JP": "", - "ko_KR": "", + "ko_KR": "다음에서 모든 PPTC 데이터를 제거하려고 합니다:\n\n{0}\n\n계속하시겠습니까?", "no_NO": "", "pl_PL": "", "pt_BR": "", @@ -19409,7 +19409,7 @@ "he_IL": "", "it_IT": "", "ja_JP": "", - "ko_KR": "", + "ko_KR": "LED 설정", "no_NO": "", "pl_PL": "", "pt_BR": "", @@ -22334,7 +22334,7 @@ "he_IL": "ממשק רשת", "it_IT": "Interfaccia di rete:", "ja_JP": "ネットワークインタフェース:", - "ko_KR": "네트워크 인터페이스:", + "ko_KR": "네트워크 인터페이스 :", "no_NO": "Nettverksgrensesnitt", "pl_PL": "Interfejs sieci:", "pt_BR": "Interface de rede:", @@ -23309,7 +23309,7 @@ "he_IL": "", "it_IT": "", "ja_JP": "", - "ko_KR": "", + "ko_KR": "최종 업데이트 : {0}", "no_NO": "Sist oppdatert: {0}", "pl_PL": "", "pt_BR": "", @@ -23684,7 +23684,7 @@ "he_IL": "", "it_IT": "", "ja_JP": "", - "ko_KR": "", + "ko_KR": "추출할 DLC 선택", "no_NO": "Velg en DLC og hente ut", "pl_PL": "", "pt_BR": "", @@ -23698,4 +23698,4 @@ } } ] -} \ No newline at end of file +} From 5e5e180feae749cecd6f12e17c8da06681ac481a Mon Sep 17 00:00:00 2001 From: Piplup <100526773+piplup55@users.noreply.github.com> Date: Thu, 6 Feb 2025 00:32:27 +0000 Subject: [PATCH 2/6] PlayReportAnalyzer: Added Pokemon Scarlet and Violet (#630) Every base game location excluding buildings are done, DLC locations will be added at a later point --- src/Ryujinx/Utilities/PlayReport.cs | 43 +++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/Ryujinx/Utilities/PlayReport.cs b/src/Ryujinx/Utilities/PlayReport.cs index f518fb902..7ebf53482 100644 --- a/src/Ryujinx/Utilities/PlayReport.cs +++ b/src/Ryujinx/Utilities/PlayReport.cs @@ -32,6 +32,12 @@ namespace Ryujinx.Ava.Utilities .AddSpec( // Global & China IDs ["0100152000022000", "010075100e8ec000"], spec => spec.AddValueFormatter("To", MarioKart8Deluxe_Mode) + ) + .AddSpec( + ["0100a3d008c5c000", "01008f6008c5e000"], + spec => spec + .AddValueFormatter("area_no", PokemonSVArea) + .AddValueFormatter("team_circle", PokemonSVUnionCircle) ); private static PlayReportFormattedValue BreathOfTheWild_MasterMode(PlayReportValue value) @@ -81,5 +87,42 @@ namespace Ryujinx.Ava.Utilities "Race" => "Racing", _ => PlayReportFormattedValue.ForceReset }; + + private static PlayReportFormattedValue PokemonSVUnionCircle(PlayReportValue value) + => value.BoxedValue is 0 ? "Playing Alone" : "Playing in a group"; + + private static PlayReportFormattedValue PokemonSVArea(PlayReportValue value) + => value.StringValue switch + { + // Base Game Locations + "a_w01" => "South Area One", + "a_w02" => "Mesagoza", + "a_w03" => "The Pokemon League", + "a_w04" => "South Area Two", + "a_w05" => "South Area Four", + "a_w06" => "South Area Six", + "a_w07" => "South Area Five", + "a_w08" => "South Area Three", + "a_w09" => "West Area One", + "a_w10" => "Asado Desert", + "a_w11" => "West Area Two", + "a_w12" => "Medali", + "a_w13" => "Tagtree Thicket", + "a_w14" => "East Area Three", + "a_w15" => "Artazon", + "a_w16" => "East Area Two", + "a_w18" => "Casseroya Lake", + "a_w19" => "Glaseado Mountain", + "a_w20" => "North Area Three", + "a_w21" => "North Area One", + "a_w22" => "North Area Two", + "a_w23" => "The Great Crater of Paldea", + "a_w24" => "South Paldean Sea", + "a_w25" => "West Paldean Sea", + "a_w26" => "East Paldean Sea", + "a_w27" => "Nouth Paldean Sea", + //TODO DLC Locations + _ => PlayReportFormattedValue.ForceReset + }; } } From c638a7daf8c1f33daaef8e8cbf5141cafd7945b5 Mon Sep 17 00:00:00 2001 From: Evan Husted Date: Wed, 5 Feb 2025 19:27:44 -0600 Subject: [PATCH 3/6] misc: chore: Move Play Report analyzer into a dedicated namespace and remove the PlayReport name prefix on types --- src/Ryujinx/DiscordIntegrationModule.cs | 10 +-- .../Analyzer.cs} | 74 +++++++++---------- .../PlayReports.cs} | 32 ++++---- 3 files changed, 56 insertions(+), 60 deletions(-) rename src/Ryujinx/Utilities/{PlayReportAnalyzer.cs => PlayReport/Analyzer.cs} (78%) rename src/Ryujinx/Utilities/{PlayReport.cs => PlayReport/PlayReports.cs} (76%) diff --git a/src/Ryujinx/DiscordIntegrationModule.cs b/src/Ryujinx/DiscordIntegrationModule.cs index 20b296511..d95bb80dd 100644 --- a/src/Ryujinx/DiscordIntegrationModule.cs +++ b/src/Ryujinx/DiscordIntegrationModule.cs @@ -4,16 +4,12 @@ using MsgPack; using Ryujinx.Ava.Utilities; using Ryujinx.Ava.Utilities.AppLibrary; using Ryujinx.Ava.Utilities.Configuration; +using Ryujinx.Ava.Utilities.PlayReport; using Ryujinx.Common; -using Ryujinx.Common.Helper; using Ryujinx.Common.Logging; using Ryujinx.HLE; using Ryujinx.HLE.Loaders.Processes; using Ryujinx.Horizon; -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; using System.Text; namespace Ryujinx.Ava @@ -130,8 +126,8 @@ namespace Ryujinx.Ava if (!TitleIDs.CurrentApplication.Value.HasValue) return; if (_discordPresencePlaying is null) return; - PlayReportAnalyzer.FormattedValue formattedValue = - PlayReport.Analyzer.Format(TitleIDs.CurrentApplication.Value, _currentApp, playReport); + Analyzer.FormattedValue formattedValue = + PlayReports.Analyzer.Format(TitleIDs.CurrentApplication.Value, _currentApp, playReport); if (!formattedValue.Handled) return; diff --git a/src/Ryujinx/Utilities/PlayReportAnalyzer.cs b/src/Ryujinx/Utilities/PlayReport/Analyzer.cs similarity index 78% rename from src/Ryujinx/Utilities/PlayReportAnalyzer.cs rename to src/Ryujinx/Utilities/PlayReport/Analyzer.cs index 47c36a396..ae5abbf9d 100644 --- a/src/Ryujinx/Utilities/PlayReportAnalyzer.cs +++ b/src/Ryujinx/Utilities/PlayReport/Analyzer.cs @@ -6,27 +6,27 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; -namespace Ryujinx.Ava.Utilities +namespace Ryujinx.Ava.Utilities.PlayReport { /// /// The entrypoint for the Play Report analysis system. /// - public class PlayReportAnalyzer + public class Analyzer { - private readonly List _specs = []; + private readonly List _specs = []; /// /// Add an analysis spec matching a specific game by title ID, with the provided spec configuration. /// /// The ID of the game to listen to Play Reports in. /// The configuration function for the analysis spec. - /// The current , for chaining convenience. - public PlayReportAnalyzer AddSpec(string titleId, Func transform) + /// The current , for chaining convenience. + public Analyzer AddSpec(string titleId, Func transform) { Guard.Ensure(ulong.TryParse(titleId, NumberStyles.HexNumber, null, out _), - $"Cannot use a non-hexadecimal string as the Title ID for a {nameof(PlayReportGameSpec)}."); + $"Cannot use a non-hexadecimal string as the Title ID for a {nameof(GameSpec)}."); - _specs.Add(transform(new PlayReportGameSpec { TitleIds = [titleId] })); + _specs.Add(transform(new GameSpec { TitleIds = [titleId] })); return this; } @@ -35,13 +35,13 @@ namespace Ryujinx.Ava.Utilities /// /// The ID of the game to listen to Play Reports in. /// The configuration function for the analysis spec. - /// The current , for chaining convenience. - public PlayReportAnalyzer AddSpec(string titleId, Action transform) + /// The current , for chaining convenience. + public Analyzer AddSpec(string titleId, Action transform) { Guard.Ensure(ulong.TryParse(titleId, NumberStyles.HexNumber, null, out _), - $"Cannot use a non-hexadecimal string as the Title ID for a {nameof(PlayReportGameSpec)}."); + $"Cannot use a non-hexadecimal string as the Title ID for a {nameof(GameSpec)}."); - _specs.Add(new PlayReportGameSpec { TitleIds = [titleId] }.Apply(transform)); + _specs.Add(new GameSpec { TitleIds = [titleId] }.Apply(transform)); return this; } @@ -50,15 +50,15 @@ namespace Ryujinx.Ava.Utilities /// /// The IDs of the games to listen to Play Reports in. /// The configuration function for the analysis spec. - /// The current , for chaining convenience. - public PlayReportAnalyzer AddSpec(IEnumerable titleIds, - Func transform) + /// The current , for chaining convenience. + public Analyzer AddSpec(IEnumerable titleIds, + Func transform) { string[] tids = titleIds.ToArray(); Guard.Ensure(tids.All(x => ulong.TryParse(x, NumberStyles.HexNumber, null, out _)), - $"Cannot use a non-hexadecimal string as the Title ID for a {nameof(PlayReportGameSpec)}."); + $"Cannot use a non-hexadecimal string as the Title ID for a {nameof(GameSpec)}."); - _specs.Add(transform(new PlayReportGameSpec { TitleIds = [..tids] })); + _specs.Add(transform(new GameSpec { TitleIds = [..tids] })); return this; } @@ -67,20 +67,20 @@ namespace Ryujinx.Ava.Utilities /// /// The IDs of the games to listen to Play Reports in. /// The configuration function for the analysis spec. - /// The current , for chaining convenience. - public PlayReportAnalyzer AddSpec(IEnumerable titleIds, Action transform) + /// The current , for chaining convenience. + public Analyzer AddSpec(IEnumerable titleIds, Action transform) { string[] tids = titleIds.ToArray(); Guard.Ensure(tids.All(x => ulong.TryParse(x, NumberStyles.HexNumber, null, out _)), - $"Cannot use a non-hexadecimal string as the Title ID for a {nameof(PlayReportGameSpec)}."); + $"Cannot use a non-hexadecimal string as the Title ID for a {nameof(GameSpec)}."); - _specs.Add(new PlayReportGameSpec { TitleIds = [..tids] }.Apply(transform)); + _specs.Add(new GameSpec { TitleIds = [..tids] }.Apply(transform)); return this; } /// - /// Runs the configured for the specified game title ID. + /// Runs the configured for the specified game title ID. /// /// The game currently running. /// The Application metadata information, including localized game name and play time information. @@ -95,15 +95,15 @@ namespace Ryujinx.Ava.Utilities if (!playReport.IsDictionary) return FormattedValue.Unhandled; - if (!_specs.TryGetFirst(s => runningGameId.EqualsAnyIgnoreCase(s.TitleIds), out PlayReportGameSpec spec)) + if (!_specs.TryGetFirst(s => runningGameId.EqualsAnyIgnoreCase(s.TitleIds), out GameSpec spec)) return FormattedValue.Unhandled; - foreach (PlayReportGameSpec.FormatterSpec formatSpec in spec.SimpleValueFormatters.OrderBy(x => x.Priority)) + foreach (GameSpec.FormatterSpec formatSpec in spec.SimpleValueFormatters.OrderBy(x => x.Priority)) { if (!playReport.AsDictionary().TryGetValue(formatSpec.ReportKey, out MessagePackObject valuePackObject)) continue; - return formatSpec.ValueFormatter(new PlayReportValue + return formatSpec.ValueFormatter(new Value { Application = appMeta, PackedValue = valuePackObject }); @@ -123,7 +123,7 @@ namespace Ryujinx.Ava.Utilities public bool Handled { get; private init; } /// - /// Did the handler request the caller of the to reset the existing value? + /// Did the handler request the caller of the to reset the existing value? /// public bool Reset { get; private init; } @@ -151,7 +151,7 @@ namespace Ryujinx.Ava.Utilities public static FormattedValue Unhandled => default; /// - /// Return this to suggest the caller reset the value it's using the for. + /// Return this to suggest the caller reset the value it's using the for. /// public static FormattedValue ForceReset => new() { Handled = true, Reset = true }; @@ -172,21 +172,21 @@ namespace Ryujinx.Ava.Utilities /// /// A mapping of title IDs to value formatter specs. /// - /// Generally speaking, use the .AddSpec(...) methods instead of creating this class yourself. + /// Generally speaking, use the .AddSpec(...) methods instead of creating this class yourself. /// - public class PlayReportGameSpec + public class GameSpec { public required string[] TitleIds { get; init; } public List SimpleValueFormatters { get; } = []; /// - /// Add a value formatter to the current + /// Add a value formatter to the current /// matching a specific key that could exist in a Play Report for the previously specified title IDs. /// /// The key name to match. /// The function which can return a potential formatted value. - /// The current , for chaining convenience. - public PlayReportGameSpec AddValueFormatter(string reportKey, PlayReportValueFormatter valueFormatter) + /// The current , for chaining convenience. + public GameSpec AddValueFormatter(string reportKey, PlayReportValueFormatter valueFormatter) { SimpleValueFormatters.Add(new FormatterSpec { @@ -196,14 +196,14 @@ namespace Ryujinx.Ava.Utilities } /// - /// Add a value formatter at a specific priority to the current + /// Add a value formatter at a specific priority to the current /// matching a specific key that could exist in a Play Report for the previously specified title IDs. /// /// The resolution priority of this value formatter. Higher resolves sooner. /// The key name to match. /// The function which can return a potential formatted value. - /// The current , for chaining convenience. - public PlayReportGameSpec AddValueFormatter(int priority, string reportKey, + /// The current , for chaining convenience. + public GameSpec AddValueFormatter(int priority, string reportKey, PlayReportValueFormatter valueFormatter) { SimpleValueFormatters.Add(new FormatterSpec @@ -229,7 +229,7 @@ namespace Ryujinx.Ava.Utilities /// containing the currently running application's , /// and the matched from the Play Report. /// - public class PlayReportValue + public class Value { /// /// The currently running application's . @@ -276,7 +276,7 @@ namespace Ryujinx.Ava.Utilities ///
/// a signal that nothing was available to handle it, ///
- /// OR a signal to reset the value that the caller is using the for. + /// OR a signal to reset the value that the caller is using the for. ///
- public delegate PlayReportAnalyzer.FormattedValue PlayReportValueFormatter(PlayReportValue value); + public delegate Analyzer.FormattedValue PlayReportValueFormatter(Value value); } diff --git a/src/Ryujinx/Utilities/PlayReport.cs b/src/Ryujinx/Utilities/PlayReport/PlayReports.cs similarity index 76% rename from src/Ryujinx/Utilities/PlayReport.cs rename to src/Ryujinx/Utilities/PlayReport/PlayReports.cs index 7ebf53482..ce35cae89 100644 --- a/src/Ryujinx/Utilities/PlayReport.cs +++ b/src/Ryujinx/Utilities/PlayReport/PlayReports.cs @@ -1,16 +1,16 @@ -using PlayReportFormattedValue = Ryujinx.Ava.Utilities.PlayReportAnalyzer.FormattedValue; +using static Ryujinx.Ava.Utilities.PlayReport.Analyzer; -namespace Ryujinx.Ava.Utilities +namespace Ryujinx.Ava.Utilities.PlayReport { - public static class PlayReport + public static class PlayReports { - public static PlayReportAnalyzer Analyzer { get; } = new PlayReportAnalyzer() + public static Analyzer Analyzer { get; } = new Analyzer() .AddSpec( "01007ef00011e000", spec => spec .AddValueFormatter("IsHardMode", BreathOfTheWild_MasterMode) // reset to normal status when switching between normal & master mode in title screen - .AddValueFormatter("AoCVer", PlayReportFormattedValue.AlwaysResets) + .AddValueFormatter("AoCVer", FormattedValue.AlwaysResets) ) .AddSpec( "0100f2c0115b6000", @@ -40,10 +40,10 @@ namespace Ryujinx.Ava.Utilities .AddValueFormatter("team_circle", PokemonSVUnionCircle) ); - private static PlayReportFormattedValue BreathOfTheWild_MasterMode(PlayReportValue value) - => value.BoxedValue is 1 ? "Playing Master Mode" : PlayReportFormattedValue.ForceReset; + private static FormattedValue BreathOfTheWild_MasterMode(Value value) + => value.BoxedValue is 1 ? "Playing Master Mode" : FormattedValue.ForceReset; - private static PlayReportFormattedValue TearsOfTheKingdom_CurrentField(PlayReportValue value) => + private static FormattedValue TearsOfTheKingdom_CurrentField(Value value) => value.DoubleValue switch { > 800d => "Exploring the Sky Islands", @@ -51,16 +51,16 @@ namespace Ryujinx.Ava.Utilities _ => "Roaming Hyrule" }; - private static PlayReportFormattedValue SuperMarioOdyssey_AssistMode(PlayReportValue value) + private static FormattedValue SuperMarioOdyssey_AssistMode(Value value) => value.BoxedValue is 1 ? "Playing in Assist Mode" : "Playing in Regular Mode"; - private static PlayReportFormattedValue SuperMarioOdysseyChina_AssistMode(PlayReportValue value) + private static FormattedValue SuperMarioOdysseyChina_AssistMode(Value value) => value.BoxedValue is 1 ? "Playing in 帮助模式" : "Playing in 普通模式"; - private static PlayReportFormattedValue SuperMario3DWorldOrBowsersFury(PlayReportValue value) + private static FormattedValue SuperMario3DWorldOrBowsersFury(Value value) => value.BoxedValue is 0 ? "Playing Super Mario 3D World" : "Playing Bowser's Fury"; - private static PlayReportFormattedValue MarioKart8Deluxe_Mode(PlayReportValue value) + private static FormattedValue MarioKart8Deluxe_Mode(Value value) => value.StringValue switch { // Single Player @@ -85,13 +85,13 @@ namespace Ryujinx.Ava.Utilities "Battle" => "Battle Mode", "RaceStart" => "Selecting a Course", "Race" => "Racing", - _ => PlayReportFormattedValue.ForceReset + _ => FormattedValue.ForceReset }; - private static PlayReportFormattedValue PokemonSVUnionCircle(PlayReportValue value) + private static FormattedValue PokemonSVUnionCircle(Value value) => value.BoxedValue is 0 ? "Playing Alone" : "Playing in a group"; - private static PlayReportFormattedValue PokemonSVArea(PlayReportValue value) + private static FormattedValue PokemonSVArea(Value value) => value.StringValue switch { // Base Game Locations @@ -122,7 +122,7 @@ namespace Ryujinx.Ava.Utilities "a_w26" => "East Paldean Sea", "a_w27" => "Nouth Paldean Sea", //TODO DLC Locations - _ => PlayReportFormattedValue.ForceReset + _ => FormattedValue.ForceReset }; } } From e55629a90855e02c6f1ca517c63c3f9fb781b905 Mon Sep 17 00:00:00 2001 From: Evan Husted Date: Wed, 5 Feb 2025 19:42:36 -0600 Subject: [PATCH 4/6] misc: chore: [ci skip] Play Report Analyzer: Added Multi Value formatters --- src/Ryujinx/Assets/locales.json | 2 +- src/Ryujinx/Utilities/PlayReport/Analyzer.cs | 63 ++++++++++++++++++- .../Utilities/PlayReport/PlayReports.cs | 8 ++- 3 files changed, 70 insertions(+), 3 deletions(-) diff --git a/src/Ryujinx/Assets/locales.json b/src/Ryujinx/Assets/locales.json index 8cf5b0d7c..5afb46c13 100644 --- a/src/Ryujinx/Assets/locales.json +++ b/src/Ryujinx/Assets/locales.json @@ -23698,4 +23698,4 @@ } } ] -} +} \ No newline at end of file diff --git a/src/Ryujinx/Utilities/PlayReport/Analyzer.cs b/src/Ryujinx/Utilities/PlayReport/Analyzer.cs index ae5abbf9d..3d0963b5a 100644 --- a/src/Ryujinx/Utilities/PlayReport/Analyzer.cs +++ b/src/Ryujinx/Utilities/PlayReport/Analyzer.cs @@ -108,6 +108,25 @@ namespace Ryujinx.Ava.Utilities.PlayReport Application = appMeta, PackedValue = valuePackObject }); } + + foreach (GameSpec.MultiFormatterSpec formatSpec in spec.MultiValueFormatters.OrderBy(x => x.Priority)) + { + List packedObjects = []; + foreach (var reportKey in formatSpec.ReportKeys) + { + if (!playReport.AsDictionary().TryGetValue(reportKey, out MessagePackObject valuePackObject)) + continue; + + packedObjects.Add(valuePackObject); + } + + if (packedObjects.Count != formatSpec.ReportKeys.Length) + return FormattedValue.Unhandled; + + return formatSpec.ValueFormatter(packedObjects + .Select(packObject => new Value { Application = appMeta, PackedValue = packObject }) + .ToArray()); + } return FormattedValue.Unhandled; } @@ -178,6 +197,7 @@ namespace Ryujinx.Ava.Utilities.PlayReport { public required string[] TitleIds { get; init; } public List SimpleValueFormatters { get; } = []; + public List MultiValueFormatters { get; } = []; /// /// Add a value formatter to the current @@ -212,6 +232,25 @@ namespace Ryujinx.Ava.Utilities.PlayReport }); return this; } + + public GameSpec AddMultiValueFormatter(string[] reportKeys, PlayReportMultiValueFormatter valueFormatter) + { + MultiValueFormatters.Add(new MultiFormatterSpec + { + Priority = SimpleValueFormatters.Count, ReportKeys = reportKeys, ValueFormatter = valueFormatter + }); + return this; + } + + public GameSpec AddMultiValueFormatter(int priority, string[] reportKeys, + PlayReportMultiValueFormatter valueFormatter) + { + MultiValueFormatters.Add(new MultiFormatterSpec + { + Priority = priority, ReportKeys = reportKeys, ValueFormatter = valueFormatter + }); + return this; + } /// /// A struct containing the data for a mapping of a key in a Play Report to a formatter for its potential value. @@ -222,6 +261,16 @@ namespace Ryujinx.Ava.Utilities.PlayReport public required string ReportKey { get; init; } public PlayReportValueFormatter ValueFormatter { get; init; } } + + /// + /// A struct containing the data for a mapping of an arbitrary key set in a Play Report to a formatter for their potential values. + /// + public struct MultiFormatterSpec + { + public required int Priority { get; init; } + public required string[] ReportKeys { get; init; } + public PlayReportMultiValueFormatter ValueFormatter { get; init; } + } } /// @@ -269,7 +318,7 @@ namespace Ryujinx.Ava.Utilities.PlayReport } /// - /// The delegate type that powers the entire analysis system (as it currently is).
+ /// The delegate type that powers single value formatters.
/// Takes in the result value from the Play Report, and outputs: ///
/// a formatted string, @@ -279,4 +328,16 @@ namespace Ryujinx.Ava.Utilities.PlayReport /// OR a signal to reset the value that the caller is using the for. ///
public delegate Analyzer.FormattedValue PlayReportValueFormatter(Value value); + + /// + /// The delegate type that powers multiple value formatters.
+ /// Takes in the result value from the Play Report, and outputs: + ///
+ /// a formatted string, + ///
+ /// a signal that nothing was available to handle it, + ///
+ /// OR a signal to reset the value that the caller is using the for. + ///
+ public delegate Analyzer.FormattedValue PlayReportMultiValueFormatter(Value[] value); } diff --git a/src/Ryujinx/Utilities/PlayReport/PlayReports.cs b/src/Ryujinx/Utilities/PlayReport/PlayReports.cs index ce35cae89..068d6bb9a 100644 --- a/src/Ryujinx/Utilities/PlayReport/PlayReports.cs +++ b/src/Ryujinx/Utilities/PlayReport/PlayReports.cs @@ -14,7 +14,8 @@ namespace Ryujinx.Ava.Utilities.PlayReport ) .AddSpec( "0100f2c0115b6000", - spec => spec.AddValueFormatter("PlayerPosY", TearsOfTheKingdom_CurrentField)) + spec => spec + .AddValueFormatter("PlayerPosY", TearsOfTheKingdom_CurrentField)) .AddSpec( "0100000000010000", spec => @@ -40,6 +41,11 @@ namespace Ryujinx.Ava.Utilities.PlayReport .AddValueFormatter("team_circle", PokemonSVUnionCircle) ); + private static FormattedValue Botw(Value[] values) + { + return $"{values[0].BoxedValue}, {values[1].BoxedValue}"; + } + private static FormattedValue BreathOfTheWild_MasterMode(Value value) => value.BoxedValue is 1 ? "Playing Master Mode" : FormattedValue.ForceReset; From 4a8f98126f38a3f82aa6e7385f9c686f4ca70a90 Mon Sep 17 00:00:00 2001 From: Evan Husted Date: Wed, 5 Feb 2025 19:45:29 -0600 Subject: [PATCH 5/6] [ci skip] remove test --- src/Ryujinx/Utilities/PlayReport/PlayReports.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Ryujinx/Utilities/PlayReport/PlayReports.cs b/src/Ryujinx/Utilities/PlayReport/PlayReports.cs index 068d6bb9a..25457744e 100644 --- a/src/Ryujinx/Utilities/PlayReport/PlayReports.cs +++ b/src/Ryujinx/Utilities/PlayReport/PlayReports.cs @@ -41,11 +41,6 @@ namespace Ryujinx.Ava.Utilities.PlayReport .AddValueFormatter("team_circle", PokemonSVUnionCircle) ); - private static FormattedValue Botw(Value[] values) - { - return $"{values[0].BoxedValue}, {values[1].BoxedValue}"; - } - private static FormattedValue BreathOfTheWild_MasterMode(Value value) => value.BoxedValue is 1 ? "Playing Master Mode" : FormattedValue.ForceReset; From d1da937fce8861ea8b5de073394dc68f8b6a6eba Mon Sep 17 00:00:00 2001 From: Evan Husted Date: Wed, 5 Feb 2025 19:51:43 -0600 Subject: [PATCH 6/6] misc: chore: [ci skip] XMLdocs on new Play Report Analyzer members --- src/Ryujinx/Utilities/PlayReport/Analyzer.cs | 45 +++++++++++++------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/src/Ryujinx/Utilities/PlayReport/Analyzer.cs b/src/Ryujinx/Utilities/PlayReport/Analyzer.cs index 3d0963b5a..84bdbf085 100644 --- a/src/Ryujinx/Utilities/PlayReport/Analyzer.cs +++ b/src/Ryujinx/Utilities/PlayReport/Analyzer.cs @@ -132,7 +132,7 @@ namespace Ryujinx.Ava.Utilities.PlayReport } /// - /// A potential formatted value returned by a . + /// A potential formatted value returned by a . /// public readonly struct FormattedValue { @@ -175,16 +175,16 @@ namespace Ryujinx.Ava.Utilities.PlayReport public static FormattedValue ForceReset => new() { Handled = true, Reset = true }; /// - /// A delegate singleton you can use to always return in a . + /// A delegate singleton you can use to always return in a . /// - public static readonly PlayReportValueFormatter AlwaysResets = _ => ForceReset; + public static readonly ValueFormatter AlwaysResets = _ => ForceReset; /// /// A delegate factory you can use to always return the specified - /// in a . + /// in a . /// /// The string to always return for this delegate instance. - public static PlayReportValueFormatter AlwaysReturns(string formattedValue) => _ => formattedValue; + public static ValueFormatter AlwaysReturns(string formattedValue) => _ => formattedValue; } } @@ -206,7 +206,7 @@ namespace Ryujinx.Ava.Utilities.PlayReport /// The key name to match. /// The function which can return a potential formatted value. /// The current , for chaining convenience. - public GameSpec AddValueFormatter(string reportKey, PlayReportValueFormatter valueFormatter) + public GameSpec AddValueFormatter(string reportKey, ValueFormatter valueFormatter) { SimpleValueFormatters.Add(new FormatterSpec { @@ -224,7 +224,7 @@ namespace Ryujinx.Ava.Utilities.PlayReport /// The function which can return a potential formatted value. /// The current , for chaining convenience. public GameSpec AddValueFormatter(int priority, string reportKey, - PlayReportValueFormatter valueFormatter) + ValueFormatter valueFormatter) { SimpleValueFormatters.Add(new FormatterSpec { @@ -233,7 +233,14 @@ namespace Ryujinx.Ava.Utilities.PlayReport return this; } - public GameSpec AddMultiValueFormatter(string[] reportKeys, PlayReportMultiValueFormatter valueFormatter) + /// + /// Add a multi-value formatter to the current + /// matching a specific set of keys that could exist in a Play Report for the previously specified title IDs. + /// + /// The key names to match. + /// The function which can format the values. + /// The current , for chaining convenience. + public GameSpec AddMultiValueFormatter(string[] reportKeys, MultiValueFormatter valueFormatter) { MultiValueFormatters.Add(new MultiFormatterSpec { @@ -242,8 +249,16 @@ namespace Ryujinx.Ava.Utilities.PlayReport return this; } + /// + /// Add a multi-value formatter at a specific priority to the current + /// matching a specific set of keys that could exist in a Play Report for the previously specified title IDs. + /// + /// The resolution priority of this value formatter. Higher resolves sooner. + /// The key names to match. + /// The function which can format the values. + /// The current , for chaining convenience. public GameSpec AddMultiValueFormatter(int priority, string[] reportKeys, - PlayReportMultiValueFormatter valueFormatter) + MultiValueFormatter valueFormatter) { MultiValueFormatters.Add(new MultiFormatterSpec { @@ -259,7 +274,7 @@ namespace Ryujinx.Ava.Utilities.PlayReport { public required int Priority { get; init; } public required string ReportKey { get; init; } - public PlayReportValueFormatter ValueFormatter { get; init; } + public ValueFormatter ValueFormatter { get; init; } } /// @@ -269,12 +284,12 @@ namespace Ryujinx.Ava.Utilities.PlayReport { public required int Priority { get; init; } public required string[] ReportKeys { get; init; } - public PlayReportMultiValueFormatter ValueFormatter { get; init; } + public MultiValueFormatter ValueFormatter { get; init; } } } /// - /// The input data to a , + /// The input data to a , /// containing the currently running application's , /// and the matched from the Play Report. /// @@ -294,7 +309,7 @@ namespace Ryujinx.Ava.Utilities.PlayReport /// Access the as its underlying .NET type.
/// /// Does not seem to work well with comparing numeric types, - /// so use and the AsX (where X is a numerical type name i.e. Int32) methods for that. + /// so use XValue properties for that. ///
public object BoxedValue => PackedValue.ToObject(); @@ -327,7 +342,7 @@ namespace Ryujinx.Ava.Utilities.PlayReport ///
/// OR a signal to reset the value that the caller is using the for. ///
- public delegate Analyzer.FormattedValue PlayReportValueFormatter(Value value); + public delegate Analyzer.FormattedValue ValueFormatter(Value value); /// /// The delegate type that powers multiple value formatters.
@@ -339,5 +354,5 @@ namespace Ryujinx.Ava.Utilities.PlayReport ///
/// OR a signal to reset the value that the caller is using the for. ///
- public delegate Analyzer.FormattedValue PlayReportMultiValueFormatter(Value[] value); + public delegate Analyzer.FormattedValue MultiValueFormatter(Value[] value); }