mirror of
https://github.com/ryujinx-mirror/ryujinx.git
synced 2026-08-14 22:13:43 +00:00
Add games/player count to Avalonia version, and retrieve asynchronously so the games list still loads if the server is down/slow
This commit is contained in:
parent
e1c7af129a
commit
b8d860192a
5 changed files with 103 additions and 20 deletions
|
|
@ -41,6 +41,7 @@ namespace Ryujinx.UI.App.Common
|
|||
public Language DesiredLanguage { get; set; }
|
||||
public event EventHandler<ApplicationAddedEventArgs> ApplicationAdded;
|
||||
public event EventHandler<ApplicationCountUpdatedEventArgs> ApplicationCountUpdated;
|
||||
public event EventHandler<LdnGameDataReceivedEventArgs> LdnGameDataReceived;
|
||||
|
||||
private readonly byte[] _nspIcon;
|
||||
private readonly byte[] _xciIcon;
|
||||
|
|
@ -565,22 +566,28 @@ namespace Ryujinx.UI.App.Common
|
|||
}
|
||||
}
|
||||
|
||||
IEnumerable<LdnGameData> ldnGameDataArray = Array.Empty<LdnGameData>();
|
||||
|
||||
if (ConfigurationState.Instance.Multiplayer.Mode == MultiplayerMode.LdnRyu)
|
||||
{
|
||||
try
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
using HttpClient httpClient = new HttpClient();
|
||||
|
||||
string ldnGameDataArrayString = await httpClient.GetStringAsync("https://ldn.ryujinx.org/api/public_games");
|
||||
|
||||
ldnGameDataArray = JsonHelper.Deserialize(ldnGameDataArrayString, _ldnDataSerializerContext.IEnumerableLdnGameData);
|
||||
}
|
||||
catch
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.Application, "Failed to fetch the public games JSON from the API. Player and game count in the game list will be unavailable.");
|
||||
}
|
||||
try
|
||||
{
|
||||
IEnumerable<LdnGameData> ldnGameDataArray = Array.Empty<LdnGameData>();
|
||||
using HttpClient httpClient = new HttpClient();
|
||||
string ldnGameDataArrayString = await httpClient.GetStringAsync("https://ldn.ryujinx.org/api/public_games");
|
||||
ldnGameDataArray = JsonHelper.Deserialize(ldnGameDataArrayString, _ldnDataSerializerContext.IEnumerableLdnGameData);
|
||||
var evt = new LdnGameDataReceivedEventArgs
|
||||
{
|
||||
LdnData = ldnGameDataArray
|
||||
};
|
||||
LdnGameDataReceived?.Invoke(null, evt);
|
||||
}
|
||||
catch
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.Application, "Failed to fetch the public games JSON from the API. Player and game count in the game list will be unavailable.");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Loops through applications list, creating a struct and then firing an event containing the struct for each application
|
||||
|
|
@ -595,14 +602,6 @@ namespace Ryujinx.UI.App.Common
|
|||
{
|
||||
foreach (var application in applications)
|
||||
{
|
||||
if (application.ControlHolder.ByteSpan.Length > 0)
|
||||
{
|
||||
IEnumerable<LdnGameData> ldnGameData = ldnGameDataArray.Where(game => application.ControlHolder.Value.LocalCommunicationId.Items.Contains(Convert.ToUInt64(game.TitleId, 16)));
|
||||
|
||||
application.PlayerCount = ldnGameData.Sum(game => game.PlayerCount);
|
||||
application.GameCount = ldnGameData.Count();
|
||||
}
|
||||
|
||||
OnApplicationAdded(new ApplicationAddedEventArgs
|
||||
{
|
||||
AppData = application,
|
||||
|
|
|
|||
11
src/Ryujinx.UI.Common/App/LdnGameDataReceivedEventArgs.cs
Normal file
11
src/Ryujinx.UI.Common/App/LdnGameDataReceivedEventArgs.cs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
using Ryujinx.Ui.Common.App;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.UI.App.Common
|
||||
{
|
||||
public class LdnGameDataReceivedEventArgs : EventArgs
|
||||
{
|
||||
public IEnumerable<LdnGameData> LdnData { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@
|
|||
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||
xmlns:converters="clr-namespace:Avalonia.Data.Converters;assembly=Avalonia.Base"
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800"
|
||||
Focusable="True"
|
||||
|
|
@ -117,6 +118,11 @@
|
|||
Text="{Binding FileExtension}"
|
||||
TextAlignment="Start"
|
||||
TextWrapping="Wrap" />
|
||||
<TextBlock
|
||||
HorizontalAlignment="Stretch"
|
||||
Text="{Binding Converter={helpers:MultiplayerInfoConverter}}"
|
||||
TextAlignment="Start"
|
||||
TextWrapping="Wrap"/>
|
||||
</StackPanel>
|
||||
<StackPanel
|
||||
Grid.Column="4"
|
||||
|
|
|
|||
44
src/Ryujinx/UI/Helpers/MultiplayerInfoConverter.cs
Normal file
44
src/Ryujinx/UI/Helpers/MultiplayerInfoConverter.cs
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
using Avalonia.Data.Converters;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.UI.App.Common;
|
||||
using Ryujinx.UI.Common.Helper;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Helpers
|
||||
{
|
||||
internal class MultiplayerInfoConverter : MarkupExtension, IValueConverter
|
||||
{
|
||||
private static readonly MultiplayerInfoConverter _instance = new();
|
||||
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value is ApplicationData applicationData)
|
||||
{
|
||||
if (applicationData.PlayerCount != 0 && applicationData.GameCount != 0)
|
||||
{
|
||||
return $"Hosted Games: {applicationData.GameCount}\nOnline Players: {applicationData.PlayerCount}";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override object ProvideValue(IServiceProvider serviceProvider)
|
||||
{
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -19,12 +19,14 @@ using Ryujinx.HLE.HOS;
|
|||
using Ryujinx.HLE.HOS.Services.Account.Acc;
|
||||
using Ryujinx.Input.HLE;
|
||||
using Ryujinx.Input.SDL2;
|
||||
using Ryujinx.Ui.Common.App;
|
||||
using Ryujinx.UI.App.Common;
|
||||
using Ryujinx.UI.Common;
|
||||
using Ryujinx.UI.Common.Configuration;
|
||||
using Ryujinx.UI.Common.Helper;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Versioning;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
|
@ -164,6 +166,26 @@ namespace Ryujinx.Ava.UI.Windows
|
|||
});
|
||||
}
|
||||
|
||||
private void ApplicationLibrary_LdnGameDataReceived(object sender, LdnGameDataReceivedEventArgs e)
|
||||
{
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
var ldnGameDataArray = e.LdnData;
|
||||
foreach (var application in ViewModel.Applications)
|
||||
{
|
||||
if (application.ControlHolder.ByteSpan.Length > 0)
|
||||
{
|
||||
IEnumerable<LdnGameData> ldnGameData = ldnGameDataArray.Where(game => application.ControlHolder.Value.LocalCommunicationId.Items.Contains(Convert.ToUInt64(game.TitleId, 16)));
|
||||
|
||||
application.PlayerCount = ldnGameData.Sum(game => game.PlayerCount);
|
||||
application.GameCount = ldnGameData.Count();
|
||||
Console.WriteLine($"PlayerCount: {application.PlayerCount}, GameCount: {application.GameCount}");
|
||||
}
|
||||
}
|
||||
ViewModel.RefreshView();
|
||||
});
|
||||
}
|
||||
|
||||
public void Application_Opened(object sender, ApplicationOpenedEventArgs args)
|
||||
{
|
||||
if (args.Application != null)
|
||||
|
|
@ -475,6 +497,7 @@ namespace Ryujinx.Ava.UI.Windows
|
|||
|
||||
ApplicationLibrary.ApplicationCountUpdated += ApplicationLibrary_ApplicationCountUpdated;
|
||||
ApplicationLibrary.ApplicationAdded += ApplicationLibrary_ApplicationAdded;
|
||||
ApplicationLibrary.LdnGameDataReceived += ApplicationLibrary_LdnGameDataReceived;
|
||||
|
||||
ViewModel.RefreshFirmwareStatus();
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue