Skip to content

Commit

Permalink
Add the ability to set a custom LDN server
Browse files Browse the repository at this point in the history
  • Loading branch information
Vudjun committed Nov 4, 2024
1 parent 8f16da8 commit 825de3d
Show file tree
Hide file tree
Showing 10 changed files with 84 additions and 11 deletions.
9 changes: 8 additions & 1 deletion src/Ryujinx.HLE/HLEConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,11 @@ public class HLEConfiguration
/// </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>
Expand Down Expand Up @@ -206,7 +211,8 @@ public HLEConfiguration(VirtualFileSystem virtualFileSystem,
string multiplayerLanInterfaceId,
MultiplayerMode multiplayerMode,
bool multiplayerDisableP2p,
string multiplayerLdnPassphrase)
string multiplayerLdnPassphrase,
string multiplayerLdnServer)
{
VirtualFileSystem = virtualFileSystem;
LibHacHorizonManager = libHacHorizonManager;
Expand Down Expand Up @@ -236,6 +242,7 @@ public HLEConfiguration(VirtualFileSystem virtualFileSystem,
MultiplayerMode = multiplayerMode;
MultiplayerDisableP2p = multiplayerDisableP2p;
MultiplayerLdnPassphrase = multiplayerLdnPassphrase;
MultiplayerLdnServer = multiplayerLdnServer;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
Expand Down Expand Up @@ -1092,15 +1092,21 @@ public ResultCode InitializeImpl(ServiceCtx context, ulong pid, int nifmRequestI
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;
Expand Down
12 changes: 9 additions & 3 deletions src/Ryujinx.UI.Common/App/ApplicationLibrary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -788,19 +789,24 @@ public async Task RefreshLdn()
{
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
{
LdnData = ldnGameDataArray
};
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>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,11 @@ public class ConfigurationFileFormat
/// </summary>
public string MultiplayerLdnPassphrase { get; set; }

/// <summary>
/// Custom LDN Server
/// </summary>
public string LdnServer { get; set; }

/// <summary>
/// Uses Hypervisor over JIT if available
/// </summary>
Expand Down
9 changes: 9 additions & 0 deletions src/Ryujinx.UI.Common/Configuration/ConfigurationState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,11 @@ public class MultiplayerSection
/// </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>();
Expand All @@ -592,6 +597,7 @@ public MultiplayerSection()
DisableP2p = new ReactiveObject<bool>();
DisableP2p.Event += static (_, e) => LogValueChange(e, nameof(DisableP2p));
LdnPassphrase = new ReactiveObject<string>();
LdnServer = new ReactiveObject<string>();
}
}

Expand Down Expand Up @@ -801,6 +807,7 @@ public ConfigurationFileFormat ToFileFormat()
MultiplayerMode = Multiplayer.Mode,
MultiplayerDisableP2p = Multiplayer.DisableP2p,
MultiplayerLdnPassphrase = Multiplayer.LdnPassphrase,
LdnServer = Multiplayer.LdnServer,
};

return configurationFile;
Expand Down Expand Up @@ -862,6 +869,7 @@ public void LoadDefault()
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;
Expand Down Expand Up @@ -1656,6 +1664,7 @@ public void Load(ConfigurationFileFormat configurationFileFormat, string configu
Multiplayer.Mode.Value = configurationFileFormat.MultiplayerMode;
Multiplayer.DisableP2p.Value = configurationFileFormat.MultiplayerDisableP2p;
Multiplayer.LdnPassphrase.Value = configurationFileFormat.MultiplayerLdnPassphrase;
Multiplayer.LdnServer.Value = configurationFileFormat.LdnServer;

if (configurationFileUpdated)
{
Expand Down
9 changes: 8 additions & 1 deletion src/Ryujinx/AppHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ public AppHost(
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();
Expand Down Expand Up @@ -498,6 +499,11 @@ private void UpdateLdnPassphraseState(object sender, ReactiveEventArgs<string> e
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;
Expand Down Expand Up @@ -878,7 +884,8 @@ private void InitializeSwitchInstance()
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()
Expand Down
6 changes: 5 additions & 1 deletion src/Ryujinx/Assets/Locales/en_US.json
Original file line number Diff line number Diff line change
Expand Up @@ -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)"
}
13 changes: 13 additions & 0 deletions src/Ryujinx/UI/ViewModels/SettingsViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ public partial class SettingsViewModel : BaseModel
private int _networkInterfaceIndex;
private int _multiplayerModeIndex;
private string _ldnPassphrase;
private string _LdnServer;

public int ResolutionScale
{
Expand Down Expand Up @@ -297,6 +298,16 @@ public int MultiplayerModeIndex

public bool IsInvalidLdnPassphraseVisible { get; set; }

public string LdnServer
{
get => _LdnServer;
set
{
_LdnServer = value;
OnPropertyChanged();
}
}

public SettingsViewModel(VirtualFileSystem virtualFileSystem, ContentManager contentManager) : this()
{
_virtualFileSystem = virtualFileSystem;
Expand Down Expand Up @@ -525,6 +536,7 @@ public void LoadCurrentConfiguration()
MultiplayerModeIndex = (int)config.Multiplayer.Mode.Value;
DisableP2P = config.Multiplayer.DisableP2p.Value;
LdnPassphrase = config.Multiplayer.LdnPassphrase.Value;
LdnServer = config.Multiplayer.LdnServer.Value;
}

public void SaveSettings()
Expand Down Expand Up @@ -643,6 +655,7 @@ public void SaveSettings()
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);

Expand Down
13 changes: 12 additions & 1 deletion src/Ryujinx/UI/Views/Settings/SettingsNetworkView.axaml
Original file line number Diff line number Diff line change
@@ -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"
Expand Down Expand Up @@ -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}">
Expand Down
5 changes: 5 additions & 0 deletions src/Ryujinx/UI/Windows/MainWindow.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,11 @@ protected override void OnOpened(EventArgs e)
{
_ = Task.Run(ViewModel.ApplicationLibrary.RefreshLdn);
};

ConfigurationState.Instance.Multiplayer.LdnServer.Event += (sender, evt) =>
{
_ = Task.Run(ViewModel.ApplicationLibrary.RefreshLdn);
};
_ = Task.Run(ViewModel.ApplicationLibrary.RefreshLdn);

ViewModel.RefreshFirmwareStatus();
Expand Down

0 comments on commit 825de3d

Please sign in to comment.