Add the ability to set a custom LDN server
This commit is contained in:
parent
8f16da8655
commit
825de3d238
@ -174,6 +174,11 @@ namespace Ryujinx.HLE
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string MultiplayerLdnPassphrase { internal get; set; }
|
public string MultiplayerLdnPassphrase { internal get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// LDN Server
|
||||||
|
/// </summary>
|
||||||
|
public string MultiplayerLdnServer { internal get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An action called when HLE force a refresh of output after docked mode changed.
|
/// An action called when HLE force a refresh of output after docked mode changed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -206,7 +211,8 @@ namespace Ryujinx.HLE
|
|||||||
string multiplayerLanInterfaceId,
|
string multiplayerLanInterfaceId,
|
||||||
MultiplayerMode multiplayerMode,
|
MultiplayerMode multiplayerMode,
|
||||||
bool multiplayerDisableP2p,
|
bool multiplayerDisableP2p,
|
||||||
string multiplayerLdnPassphrase)
|
string multiplayerLdnPassphrase,
|
||||||
|
string multiplayerLdnServer)
|
||||||
{
|
{
|
||||||
VirtualFileSystem = virtualFileSystem;
|
VirtualFileSystem = virtualFileSystem;
|
||||||
LibHacHorizonManager = libHacHorizonManager;
|
LibHacHorizonManager = libHacHorizonManager;
|
||||||
@ -236,6 +242,7 @@ namespace Ryujinx.HLE
|
|||||||
MultiplayerMode = multiplayerMode;
|
MultiplayerMode = multiplayerMode;
|
||||||
MultiplayerDisableP2p = multiplayerDisableP2p;
|
MultiplayerDisableP2p = multiplayerDisableP2p;
|
||||||
MultiplayerLdnPassphrase = multiplayerLdnPassphrase;
|
MultiplayerLdnPassphrase = multiplayerLdnPassphrase;
|
||||||
|
MultiplayerLdnServer = multiplayerLdnServer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator
|
|||||||
{
|
{
|
||||||
class IUserLocalCommunicationService : IpcService, IDisposable
|
class IUserLocalCommunicationService : IpcService, IDisposable
|
||||||
{
|
{
|
||||||
public static string LanPlayHost = "ryuldn.vudjun.com";
|
public static string DefaultLanPlayHost = "ryuldn.vudjun.com";
|
||||||
public static short LanPlayPort = 30456;
|
public static short LanPlayPort = 30456;
|
||||||
|
|
||||||
public INetworkClient NetworkClient { get; private set; }
|
public INetworkClient NetworkClient { get; private set; }
|
||||||
@ -1092,15 +1092,21 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator
|
|||||||
case MultiplayerMode.LdnRyu:
|
case MultiplayerMode.LdnRyu:
|
||||||
try
|
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);
|
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, "Could not locate LdnRyu server. Defaulting to stubbed wireless.");
|
||||||
|
Logger.Error?.Print(LogClass.ServiceLdn, ex.Message);
|
||||||
NetworkClient = new LdnDisabledClient();
|
NetworkClient = new LdnDisabledClient();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -44,6 +44,7 @@ namespace Ryujinx.UI.App.Common
|
|||||||
{
|
{
|
||||||
public class ApplicationLibrary
|
public class ApplicationLibrary
|
||||||
{
|
{
|
||||||
|
public static string DefaultLanPlayWebHost = "ryuldnweb.vudjun.com";
|
||||||
public Language DesiredLanguage { get; set; }
|
public Language DesiredLanguage { get; set; }
|
||||||
public event EventHandler<ApplicationCountUpdatedEventArgs> ApplicationCountUpdated;
|
public event EventHandler<ApplicationCountUpdatedEventArgs> ApplicationCountUpdated;
|
||||||
public event EventHandler<LdnGameDataReceivedEventArgs> LdnGameDataReceived;
|
public event EventHandler<LdnGameDataReceivedEventArgs> LdnGameDataReceived;
|
||||||
@ -788,9 +789,14 @@ namespace Ryujinx.UI.App.Common
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
string ldnWebHost = ConfigurationState.Instance.Multiplayer.LdnServer;
|
||||||
|
if (string.IsNullOrEmpty(ldnWebHost))
|
||||||
|
{
|
||||||
|
ldnWebHost = DefaultLanPlayWebHost;
|
||||||
|
}
|
||||||
IEnumerable<LdnGameData> ldnGameDataArray = Array.Empty<LdnGameData>();
|
IEnumerable<LdnGameData> ldnGameDataArray = Array.Empty<LdnGameData>();
|
||||||
using HttpClient httpClient = new HttpClient();
|
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);
|
ldnGameDataArray = JsonHelper.Deserialize(ldnGameDataArrayString, _ldnDataSerializerContext.IEnumerableLdnGameData);
|
||||||
var evt = new LdnGameDataReceivedEventArgs
|
var evt = new LdnGameDataReceivedEventArgs
|
||||||
{
|
{
|
||||||
@ -798,9 +804,9 @@ namespace Ryujinx.UI.App.Common
|
|||||||
};
|
};
|
||||||
LdnGameDataReceived?.Invoke(null, evt);
|
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()
|
LdnGameDataReceived?.Invoke(null, new LdnGameDataReceivedEventArgs()
|
||||||
{
|
{
|
||||||
LdnData = Array.Empty<LdnGameData>()
|
LdnData = Array.Empty<LdnGameData>()
|
||||||
|
@ -402,6 +402,11 @@ namespace Ryujinx.UI.Common.Configuration
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string MultiplayerLdnPassphrase { get; set; }
|
public string MultiplayerLdnPassphrase { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Custom LDN Server
|
||||||
|
/// </summary>
|
||||||
|
public string LdnServer { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Uses Hypervisor over JIT if available
|
/// Uses Hypervisor over JIT if available
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -584,6 +584,11 @@ namespace Ryujinx.UI.Common.Configuration
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public ReactiveObject<string> LdnPassphrase { get; private set; }
|
public ReactiveObject<string> LdnPassphrase { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Custom LDN server
|
||||||
|
/// </summary>
|
||||||
|
public ReactiveObject<string> LdnServer { get; private set; }
|
||||||
|
|
||||||
public MultiplayerSection()
|
public MultiplayerSection()
|
||||||
{
|
{
|
||||||
LanInterfaceId = new ReactiveObject<string>();
|
LanInterfaceId = new ReactiveObject<string>();
|
||||||
@ -592,6 +597,7 @@ namespace Ryujinx.UI.Common.Configuration
|
|||||||
DisableP2p = new ReactiveObject<bool>();
|
DisableP2p = new ReactiveObject<bool>();
|
||||||
DisableP2p.Event += static (_, e) => LogValueChange(e, nameof(DisableP2p));
|
DisableP2p.Event += static (_, e) => LogValueChange(e, nameof(DisableP2p));
|
||||||
LdnPassphrase = new ReactiveObject<string>();
|
LdnPassphrase = new ReactiveObject<string>();
|
||||||
|
LdnServer = new ReactiveObject<string>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -801,6 +807,7 @@ namespace Ryujinx.UI.Common.Configuration
|
|||||||
MultiplayerMode = Multiplayer.Mode,
|
MultiplayerMode = Multiplayer.Mode,
|
||||||
MultiplayerDisableP2p = Multiplayer.DisableP2p,
|
MultiplayerDisableP2p = Multiplayer.DisableP2p,
|
||||||
MultiplayerLdnPassphrase = Multiplayer.LdnPassphrase,
|
MultiplayerLdnPassphrase = Multiplayer.LdnPassphrase,
|
||||||
|
LdnServer = Multiplayer.LdnServer,
|
||||||
};
|
};
|
||||||
|
|
||||||
return configurationFile;
|
return configurationFile;
|
||||||
@ -862,6 +869,7 @@ namespace Ryujinx.UI.Common.Configuration
|
|||||||
Multiplayer.Mode.Value = MultiplayerMode.Disabled;
|
Multiplayer.Mode.Value = MultiplayerMode.Disabled;
|
||||||
Multiplayer.DisableP2p.Value = false;
|
Multiplayer.DisableP2p.Value = false;
|
||||||
Multiplayer.LdnPassphrase.Value = "";
|
Multiplayer.LdnPassphrase.Value = "";
|
||||||
|
Multiplayer.LdnServer.Value = "";
|
||||||
UI.GuiColumns.FavColumn.Value = true;
|
UI.GuiColumns.FavColumn.Value = true;
|
||||||
UI.GuiColumns.IconColumn.Value = true;
|
UI.GuiColumns.IconColumn.Value = true;
|
||||||
UI.GuiColumns.AppColumn.Value = true;
|
UI.GuiColumns.AppColumn.Value = true;
|
||||||
@ -1656,6 +1664,7 @@ namespace Ryujinx.UI.Common.Configuration
|
|||||||
Multiplayer.Mode.Value = configurationFileFormat.MultiplayerMode;
|
Multiplayer.Mode.Value = configurationFileFormat.MultiplayerMode;
|
||||||
Multiplayer.DisableP2p.Value = configurationFileFormat.MultiplayerDisableP2p;
|
Multiplayer.DisableP2p.Value = configurationFileFormat.MultiplayerDisableP2p;
|
||||||
Multiplayer.LdnPassphrase.Value = configurationFileFormat.MultiplayerLdnPassphrase;
|
Multiplayer.LdnPassphrase.Value = configurationFileFormat.MultiplayerLdnPassphrase;
|
||||||
|
Multiplayer.LdnServer.Value = configurationFileFormat.LdnServer;
|
||||||
|
|
||||||
if (configurationFileUpdated)
|
if (configurationFileUpdated)
|
||||||
{
|
{
|
||||||
|
@ -208,6 +208,7 @@ namespace Ryujinx.Ava
|
|||||||
ConfigurationState.Instance.Multiplayer.LanInterfaceId.Event += UpdateLanInterfaceIdState;
|
ConfigurationState.Instance.Multiplayer.LanInterfaceId.Event += UpdateLanInterfaceIdState;
|
||||||
ConfigurationState.Instance.Multiplayer.Mode.Event += UpdateMultiplayerModeState;
|
ConfigurationState.Instance.Multiplayer.Mode.Event += UpdateMultiplayerModeState;
|
||||||
ConfigurationState.Instance.Multiplayer.LdnPassphrase.Event += UpdateLdnPassphraseState;
|
ConfigurationState.Instance.Multiplayer.LdnPassphrase.Event += UpdateLdnPassphraseState;
|
||||||
|
ConfigurationState.Instance.Multiplayer.LdnServer.Event += UpdateLdnServerState;
|
||||||
ConfigurationState.Instance.Multiplayer.DisableP2p.Event += UpdateDisableP2pState;
|
ConfigurationState.Instance.Multiplayer.DisableP2p.Event += UpdateDisableP2pState;
|
||||||
|
|
||||||
_gpuCancellationTokenSource = new CancellationTokenSource();
|
_gpuCancellationTokenSource = new CancellationTokenSource();
|
||||||
@ -498,6 +499,11 @@ namespace Ryujinx.Ava
|
|||||||
Device.Configuration.MultiplayerLdnPassphrase = e.NewValue;
|
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)
|
private void UpdateDisableP2pState(object sender, ReactiveEventArgs<bool> e)
|
||||||
{
|
{
|
||||||
Device.Configuration.MultiplayerDisableP2p = e.NewValue;
|
Device.Configuration.MultiplayerDisableP2p = e.NewValue;
|
||||||
@ -878,7 +884,8 @@ namespace Ryujinx.Ava
|
|||||||
ConfigurationState.Instance.Multiplayer.LanInterfaceId.Value,
|
ConfigurationState.Instance.Multiplayer.LanInterfaceId.Value,
|
||||||
ConfigurationState.Instance.Multiplayer.Mode,
|
ConfigurationState.Instance.Multiplayer.Mode,
|
||||||
ConfigurationState.Instance.Multiplayer.DisableP2p,
|
ConfigurationState.Instance.Multiplayer.DisableP2p,
|
||||||
ConfigurationState.Instance.Multiplayer.LdnPassphrase));
|
ConfigurationState.Instance.Multiplayer.LdnPassphrase,
|
||||||
|
ConfigurationState.Instance.Multiplayer.LdnServer));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IHardwareDeviceDriver InitializeAudio()
|
private static IHardwareDeviceDriver InitializeAudio()
|
||||||
|
@ -819,5 +819,9 @@
|
|||||||
"GenLdnPassTooltip": "Generates a new passphrase, which can be shared with other players.",
|
"GenLdnPassTooltip": "Generates a new passphrase, which can be shared with other players.",
|
||||||
"ClearLdnPass": "Clear",
|
"ClearLdnPass": "Clear",
|
||||||
"ClearLdnPassTooltip": "Clears the current passphrase, returning to the public network.",
|
"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)"
|
||||||
}
|
}
|
||||||
|
@ -58,6 +58,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
private int _networkInterfaceIndex;
|
private int _networkInterfaceIndex;
|
||||||
private int _multiplayerModeIndex;
|
private int _multiplayerModeIndex;
|
||||||
private string _ldnPassphrase;
|
private string _ldnPassphrase;
|
||||||
|
private string _LdnServer;
|
||||||
|
|
||||||
public int ResolutionScale
|
public int ResolutionScale
|
||||||
{
|
{
|
||||||
@ -297,6 +298,16 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
|
|
||||||
public bool IsInvalidLdnPassphraseVisible { get; set; }
|
public bool IsInvalidLdnPassphraseVisible { get; set; }
|
||||||
|
|
||||||
|
public string LdnServer
|
||||||
|
{
|
||||||
|
get => _LdnServer;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_LdnServer = value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public SettingsViewModel(VirtualFileSystem virtualFileSystem, ContentManager contentManager) : this()
|
public SettingsViewModel(VirtualFileSystem virtualFileSystem, ContentManager contentManager) : this()
|
||||||
{
|
{
|
||||||
_virtualFileSystem = virtualFileSystem;
|
_virtualFileSystem = virtualFileSystem;
|
||||||
@ -525,6 +536,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
MultiplayerModeIndex = (int)config.Multiplayer.Mode.Value;
|
MultiplayerModeIndex = (int)config.Multiplayer.Mode.Value;
|
||||||
DisableP2P = config.Multiplayer.DisableP2p.Value;
|
DisableP2P = config.Multiplayer.DisableP2p.Value;
|
||||||
LdnPassphrase = config.Multiplayer.LdnPassphrase.Value;
|
LdnPassphrase = config.Multiplayer.LdnPassphrase.Value;
|
||||||
|
LdnServer = config.Multiplayer.LdnServer.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SaveSettings()
|
public void SaveSettings()
|
||||||
@ -643,6 +655,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
config.Multiplayer.Mode.Value = (MultiplayerMode)MultiplayerModeIndex;
|
config.Multiplayer.Mode.Value = (MultiplayerMode)MultiplayerModeIndex;
|
||||||
config.Multiplayer.DisableP2p.Value = DisableP2P;
|
config.Multiplayer.DisableP2p.Value = DisableP2P;
|
||||||
config.Multiplayer.LdnPassphrase.Value = LdnPassphrase;
|
config.Multiplayer.LdnPassphrase.Value = LdnPassphrase;
|
||||||
|
config.Multiplayer.LdnServer.Value = LdnServer;
|
||||||
|
|
||||||
config.ToFileFormat().SaveConfig(Program.ConfigurationPath);
|
config.ToFileFormat().SaveConfig(Program.ConfigurationPath);
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<UserControl
|
<UserControl
|
||||||
x:Class="Ryujinx.Ava.UI.Views.Settings.SettingsNetworkView"
|
x:Class="Ryujinx.Ava.UI.Views.Settings.SettingsNetworkView"
|
||||||
xmlns="https://github.com/avaloniaui"
|
xmlns="https://github.com/avaloniaui"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
@ -87,6 +87,17 @@
|
|||||||
IsVisible="{Binding IsInvalidLdnPassphraseVisible}"
|
IsVisible="{Binding IsInvalidLdnPassphraseVisible}"
|
||||||
Focusable="False"
|
Focusable="False"
|
||||||
Text="{ext:Locale InvalidLdnPassphrase}" />
|
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" />
|
<Separator Height="1" />
|
||||||
<TextBlock Classes="h1" Text="{ext:Locale SettingsTabNetworkConnection}" />
|
<TextBlock Classes="h1" Text="{ext:Locale SettingsTabNetworkConnection}" />
|
||||||
<CheckBox Margin="10,0,0,0" IsChecked="{Binding EnableInternetAccess}">
|
<CheckBox Margin="10,0,0,0" IsChecked="{Binding EnableInternetAccess}">
|
||||||
|
@ -501,6 +501,11 @@ namespace Ryujinx.Ava.UI.Windows
|
|||||||
{
|
{
|
||||||
_ = Task.Run(ViewModel.ApplicationLibrary.RefreshLdn);
|
_ = Task.Run(ViewModel.ApplicationLibrary.RefreshLdn);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ConfigurationState.Instance.Multiplayer.LdnServer.Event += (sender, evt) =>
|
||||||
|
{
|
||||||
|
_ = Task.Run(ViewModel.ApplicationLibrary.RefreshLdn);
|
||||||
|
};
|
||||||
_ = Task.Run(ViewModel.ApplicationLibrary.RefreshLdn);
|
_ = Task.Run(ViewModel.ApplicationLibrary.RefreshLdn);
|
||||||
|
|
||||||
ViewModel.RefreshFirmwareStatus();
|
ViewModel.RefreshFirmwareStatus();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user