Add the ability to set a custom LDN server

This commit is contained in:
Vudjun 2024-11-04 18:32:14 +00:00
parent 8f16da8655
commit 825de3d238
10 changed files with 84 additions and 11 deletions

View File

@ -174,6 +174,11 @@ namespace Ryujinx.HLE
/// </summary>
public string MultiplayerLdnPassphrase { internal get; set; }
/// <summary>
/// LDN Server
/// </summary>
public string MultiplayerLdnServer { internal get; set; }
/// <summary>
/// An action called when HLE force a refresh of output after docked mode changed.
/// </summary>
@ -206,7 +211,8 @@ namespace Ryujinx.HLE
string multiplayerLanInterfaceId,
MultiplayerMode multiplayerMode,
bool multiplayerDisableP2p,
string multiplayerLdnPassphrase)
string multiplayerLdnPassphrase,
string multiplayerLdnServer)
{
VirtualFileSystem = virtualFileSystem;
LibHacHorizonManager = libHacHorizonManager;
@ -236,6 +242,7 @@ namespace Ryujinx.HLE
MultiplayerMode = multiplayerMode;
MultiplayerDisableP2p = multiplayerDisableP2p;
MultiplayerLdnPassphrase = multiplayerLdnPassphrase;
MultiplayerLdnServer = multiplayerLdnServer;
}
}
}

View File

@ -23,7 +23,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator
{
class IUserLocalCommunicationService : IpcService, IDisposable
{
public static string LanPlayHost = "ryuldn.vudjun.com";
public static string DefaultLanPlayHost = "ryuldn.vudjun.com";
public static short LanPlayPort = 30456;
public INetworkClient NetworkClient { get; private set; }
@ -1092,15 +1092,21 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator
case MultiplayerMode.LdnRyu:
try
{
if (!IPAddress.TryParse(LanPlayHost, out IPAddress ipAddress))
string ldnServer = context.Device.Configuration.MultiplayerLdnServer;
if (string.IsNullOrEmpty(ldnServer))
{
ipAddress = Dns.GetHostEntry(LanPlayHost).AddressList[0];
ldnServer = DefaultLanPlayHost;
}
if (!IPAddress.TryParse(ldnServer, out IPAddress ipAddress))
{
ipAddress = Dns.GetHostEntry(ldnServer).AddressList[0];
}
NetworkClient = new LdnMasterProxyClient(ipAddress.ToString(), LanPlayPort, context.Device.Configuration);
}
catch (Exception)
catch (Exception ex)
{
Logger.Error?.Print(LogClass.ServiceLdn, "Could not locate LdnRyu server. Defaulting to stubbed wireless.");
Logger.Error?.Print(LogClass.ServiceLdn, ex.Message);
NetworkClient = new LdnDisabledClient();
}
break;

View File

@ -44,6 +44,7 @@ namespace Ryujinx.UI.App.Common
{
public class ApplicationLibrary
{
public static string DefaultLanPlayWebHost = "ryuldnweb.vudjun.com";
public Language DesiredLanguage { get; set; }
public event EventHandler<ApplicationCountUpdatedEventArgs> ApplicationCountUpdated;
public event EventHandler<LdnGameDataReceivedEventArgs> LdnGameDataReceived;
@ -788,9 +789,14 @@ namespace Ryujinx.UI.App.Common
{
try
{
string ldnWebHost = ConfigurationState.Instance.Multiplayer.LdnServer;
if (string.IsNullOrEmpty(ldnWebHost))
{
ldnWebHost = DefaultLanPlayWebHost;
}
IEnumerable<LdnGameData> ldnGameDataArray = Array.Empty<LdnGameData>();
using HttpClient httpClient = new HttpClient();
string ldnGameDataArrayString = await httpClient.GetStringAsync("https://ryuldnweb.vudjun.com/api/public_games");
string ldnGameDataArrayString = await httpClient.GetStringAsync($"https://{ldnWebHost}/api/public_games");
ldnGameDataArray = JsonHelper.Deserialize(ldnGameDataArrayString, _ldnDataSerializerContext.IEnumerableLdnGameData);
var evt = new LdnGameDataReceivedEventArgs
{
@ -798,9 +804,9 @@ namespace Ryujinx.UI.App.Common
};
LdnGameDataReceived?.Invoke(null, evt);
}
catch
catch (Exception ex)
{
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.");
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.\n{ex.Message}");
LdnGameDataReceived?.Invoke(null, new LdnGameDataReceivedEventArgs()
{
LdnData = Array.Empty<LdnGameData>()

View File

@ -402,6 +402,11 @@ namespace Ryujinx.UI.Common.Configuration
/// </summary>
public string MultiplayerLdnPassphrase { get; set; }
/// <summary>
/// Custom LDN Server
/// </summary>
public string LdnServer { get; set; }
/// <summary>
/// Uses Hypervisor over JIT if available
/// </summary>

View File

@ -584,6 +584,11 @@ namespace Ryujinx.UI.Common.Configuration
/// </summary>
public ReactiveObject<string> LdnPassphrase { get; private set; }
/// <summary>
/// Custom LDN server
/// </summary>
public ReactiveObject<string> LdnServer { get; private set; }
public MultiplayerSection()
{
LanInterfaceId = new ReactiveObject<string>();
@ -592,6 +597,7 @@ namespace Ryujinx.UI.Common.Configuration
DisableP2p = new ReactiveObject<bool>();
DisableP2p.Event += static (_, e) => LogValueChange(e, nameof(DisableP2p));
LdnPassphrase = new ReactiveObject<string>();
LdnServer = new ReactiveObject<string>();
}
}
@ -801,6 +807,7 @@ namespace Ryujinx.UI.Common.Configuration
MultiplayerMode = Multiplayer.Mode,
MultiplayerDisableP2p = Multiplayer.DisableP2p,
MultiplayerLdnPassphrase = Multiplayer.LdnPassphrase,
LdnServer = Multiplayer.LdnServer,
};
return configurationFile;
@ -862,6 +869,7 @@ namespace Ryujinx.UI.Common.Configuration
Multiplayer.Mode.Value = MultiplayerMode.Disabled;
Multiplayer.DisableP2p.Value = false;
Multiplayer.LdnPassphrase.Value = "";
Multiplayer.LdnServer.Value = "";
UI.GuiColumns.FavColumn.Value = true;
UI.GuiColumns.IconColumn.Value = true;
UI.GuiColumns.AppColumn.Value = true;
@ -1656,6 +1664,7 @@ namespace Ryujinx.UI.Common.Configuration
Multiplayer.Mode.Value = configurationFileFormat.MultiplayerMode;
Multiplayer.DisableP2p.Value = configurationFileFormat.MultiplayerDisableP2p;
Multiplayer.LdnPassphrase.Value = configurationFileFormat.MultiplayerLdnPassphrase;
Multiplayer.LdnServer.Value = configurationFileFormat.LdnServer;
if (configurationFileUpdated)
{

View File

@ -208,6 +208,7 @@ namespace Ryujinx.Ava
ConfigurationState.Instance.Multiplayer.LanInterfaceId.Event += UpdateLanInterfaceIdState;
ConfigurationState.Instance.Multiplayer.Mode.Event += UpdateMultiplayerModeState;
ConfigurationState.Instance.Multiplayer.LdnPassphrase.Event += UpdateLdnPassphraseState;
ConfigurationState.Instance.Multiplayer.LdnServer.Event += UpdateLdnServerState;
ConfigurationState.Instance.Multiplayer.DisableP2p.Event += UpdateDisableP2pState;
_gpuCancellationTokenSource = new CancellationTokenSource();
@ -498,6 +499,11 @@ namespace Ryujinx.Ava
Device.Configuration.MultiplayerLdnPassphrase = e.NewValue;
}
private void UpdateLdnServerState(object sender, ReactiveEventArgs<string> e)
{
Device.Configuration.MultiplayerLdnServer = e.NewValue;
}
private void UpdateDisableP2pState(object sender, ReactiveEventArgs<bool> e)
{
Device.Configuration.MultiplayerDisableP2p = e.NewValue;
@ -878,7 +884,8 @@ namespace Ryujinx.Ava
ConfigurationState.Instance.Multiplayer.LanInterfaceId.Value,
ConfigurationState.Instance.Multiplayer.Mode,
ConfigurationState.Instance.Multiplayer.DisableP2p,
ConfigurationState.Instance.Multiplayer.LdnPassphrase));
ConfigurationState.Instance.Multiplayer.LdnPassphrase,
ConfigurationState.Instance.Multiplayer.LdnServer));
}
private static IHardwareDeviceDriver InitializeAudio()

View File

@ -819,5 +819,9 @@
"GenLdnPassTooltip": "Generates a new passphrase, which can be shared with other players.",
"ClearLdnPass": "Clear",
"ClearLdnPassTooltip": "Clears the current passphrase, returning to the public network.",
"InvalidLdnPassphrase": "Invalid Passphrase! Must be in the format \"Ryujinx-<8 hex chars>\""
"InvalidLdnPassphrase": "Invalid Passphrase! Must be in the format \"Ryujinx-<8 hex chars>\"",
"LdnServer": "Custom LDN Server:",
"LdnServerTooltip": "The LDN server to use for LDN connections. Leave blank to use the default server.",
"LdnServerInputTooltip": "Enter the URL of the LDN server to use.",
"LdnServerInputDefault": "(default)"
}

View File

@ -58,6 +58,7 @@ namespace Ryujinx.Ava.UI.ViewModels
private int _networkInterfaceIndex;
private int _multiplayerModeIndex;
private string _ldnPassphrase;
private string _LdnServer;
public int ResolutionScale
{
@ -297,6 +298,16 @@ namespace Ryujinx.Ava.UI.ViewModels
public bool IsInvalidLdnPassphraseVisible { get; set; }
public string LdnServer
{
get => _LdnServer;
set
{
_LdnServer = value;
OnPropertyChanged();
}
}
public SettingsViewModel(VirtualFileSystem virtualFileSystem, ContentManager contentManager) : this()
{
_virtualFileSystem = virtualFileSystem;
@ -525,6 +536,7 @@ namespace Ryujinx.Ava.UI.ViewModels
MultiplayerModeIndex = (int)config.Multiplayer.Mode.Value;
DisableP2P = config.Multiplayer.DisableP2p.Value;
LdnPassphrase = config.Multiplayer.LdnPassphrase.Value;
LdnServer = config.Multiplayer.LdnServer.Value;
}
public void SaveSettings()
@ -643,6 +655,7 @@ namespace Ryujinx.Ava.UI.ViewModels
config.Multiplayer.Mode.Value = (MultiplayerMode)MultiplayerModeIndex;
config.Multiplayer.DisableP2p.Value = DisableP2P;
config.Multiplayer.LdnPassphrase.Value = LdnPassphrase;
config.Multiplayer.LdnServer.Value = LdnServer;
config.ToFileFormat().SaveConfig(Program.ConfigurationPath);

View File

@ -1,4 +1,4 @@
<UserControl
<UserControl
x:Class="Ryujinx.Ava.UI.Views.Settings.SettingsNetworkView"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
@ -87,6 +87,17 @@
IsVisible="{Binding IsInvalidLdnPassphraseVisible}"
Focusable="False"
Text="{ext:Locale InvalidLdnPassphrase}" />
<StackPanel Margin="10,0,0,0" Orientation="Horizontal">
<TextBlock VerticalAlignment="Center"
Text="{ext:Locale LdnServer}"
ToolTip.Tip="{ext:Locale LdnServerTooltip}"
Width="200" />
<TextBox Name="LdnServer"
Text="{Binding LdnServer}"
Width="250"
ToolTip.Tip="{ext:Locale LdnServerInputTooltip}"
Watermark="{ext:Locale LdnServerInputDefault}" />
</StackPanel>
<Separator Height="1" />
<TextBlock Classes="h1" Text="{ext:Locale SettingsTabNetworkConnection}" />
<CheckBox Margin="10,0,0,0" IsChecked="{Binding EnableInternetAccess}">

View File

@ -501,6 +501,11 @@ namespace Ryujinx.Ava.UI.Windows
{
_ = Task.Run(ViewModel.ApplicationLibrary.RefreshLdn);
};
ConfigurationState.Instance.Multiplayer.LdnServer.Event += (sender, evt) =>
{
_ = Task.Run(ViewModel.ApplicationLibrary.RefreshLdn);
};
_ = Task.Run(ViewModel.ApplicationLibrary.RefreshLdn);
ViewModel.RefreshFirmwareStatus();