Skip to content
Open
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
66c9063
Bump cncnet protocol version
11EJDE11 Oct 5, 2025
ac9a9b3
Add UseLegacyTunnels and UseDynamicTunnels settings
11EJDE11 Oct 5, 2025
94a006b
Add check for tunnelling method when receiving game broadcasts
11EJDE11 Oct 5, 2025
732152e
Allow displaying and selecting V3 tunnels in TunnelListBox
11EJDE11 Oct 5, 2025
787eec3
Update ping text in GameInformationPanel when dynamic tunnels are ena…
11EJDE11 Oct 5, 2025
9127d7f
Allow lobbies to be created with V3 tunnels
11EJDE11 Oct 5, 2025
8f9e69d
Fix null ping crash when hosted game uses dynamic tunnels
11EJDE11 Oct 5, 2025
0f85089
Add V3PlayerInfo
11EJDE11 Oct 8, 2025
bff149e
Add tunnel version to /tunnelinfo chatbox command
11EJDE11 Oct 9, 2025
515a38a
Separate out negotiation status information into new file
11EJDE11 Oct 9, 2025
ab92b94
Update lobby ping indicators
11EJDE11 Oct 9, 2025
10628a0
Merge NEGSTAT and NEGPNG CTCP messages > NEGINFO
11EJDE11 Oct 9, 2025
17a7f88
Reset pings on TunnelModeChange
11EJDE11 Oct 9, 2025
b455845
Change to ping distinct IPs and update others
11EJDE11 Oct 9, 2025
5733cf1
Remove debug call
11EJDE11 Oct 9, 2025
eddf60d
Rename files
11EJDE11 Oct 9, 2025
c2da73d
Add final ping to the tunnel choice packet send to non-decider
11EJDE11 Oct 9, 2025
f7e442a
Rearrange some functions
11EJDE11 Oct 10, 2025
fa4b6e7
Prevent duplicate complete messages
11EJDE11 Oct 11, 2025
34c49f6
Increase timeout
11EJDE11 Oct 11, 2025
3f4269b
Merge branch 'develop' into new-v3-tunnels
11EJDE11 Nov 22, 2025
caf9f1e
Add nullable to various files
11EJDE11 Nov 22, 2025
8cb2735
Fix ping check
11EJDE11 Nov 22, 2025
288f91e
Remove unnecessary if statement
11EJDE11 Nov 22, 2025
8ff6d06
Fix nullable issues
11EJDE11 Nov 22, 2025
1723234
Fix endianness
11EJDE11 Nov 22, 2025
80f4769
More nullable fixups
11EJDE11 Nov 22, 2025
aba4aad
More nullable fixups
11EJDE11 Nov 22, 2025
7752275
Store pings as PingValue record instead of integers
11EJDE11 Dec 3, 2025
a577951
Update TunnelInfo lobby command
11EJDE11 Dec 3, 2025
65f168f
Merge remote-tracking branch 'origin/develop' into new-v3-tunnels
11EJDE11 Dec 6, 2025
24366a9
Merge remote-tracking branch 'origin/develop' into new-v3-tunnels
11EJDE11 Dec 26, 2025
c849e5a
Fix negotiator leak
11EJDE11 Dec 26, 2025
43a0339
Update early selection threshold
11EJDE11 Dec 26, 2025
bae1fdd
Fix comment
11EJDE11 Dec 26, 2025
1e9333f
Temp test
11EJDE11 Dec 31, 2025
5ea8ac0
Undo temp change
11EJDE11 Dec 31, 2025
dd5f5e5
Merge with develop
11EJDE11 Jan 24, 2026
98442ba
Merge branch 'develop' into new-v3-tunnels
11EJDE11 Jan 24, 2026
c8f8d0f
Fix header alignment in negotiation status panel
11EJDE11 Jan 24, 2026
9dd924e
Update protocol revision to shave off 4 bytes
11EJDE11 Jan 24, 2026
0133a03
Add summary comments
11EJDE11 Jan 24, 2026
5b9f62b
Add exception when requesting negotiation status between same player
11EJDE11 Jan 24, 2026
8508ca0
Change FromMS to conditional expression
11EJDE11 Jan 24, 2026
45b19b5
Avoid unnecessary task creation
11EJDE11 Jan 24, 2026
df9e132
Fix formatting, spelling, and grammar
11EJDE11 Jan 24, 2026
f051920
Use icons for negotiation status instead of chat messages
11EJDE11 Jan 24, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ClientCore/ProgramConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public static class ProgramConstants

public const string QRES_EXECUTABLE = "qres.dat";

public const string CNCNET_PROTOCOL_REVISION = "R13";
public const string CNCNET_PROTOCOL_REVISION = "R15";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could save a character from GameSurge traffic by using alphabetics for the number instead.

RF for example. We could also drop the R to save two bytes - it used to be short for Rampastring to differentiate my protocol from Funky's client, but I don't think that's a major consideration anymore.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

public const string LAN_PROTOCOL_REVISION = "RL8";
public const int LAN_PORT = 1234;
public const int LAN_INGAME_PORT = 1234;
Expand Down
6 changes: 6 additions & 0 deletions ClientCore/Settings/UserINISettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,9 @@ protected UserINISettings(IniFile iniFile)
MapSortState = new IntSetting(iniFile, MULTIPLAYER, "MapSortState", (int)SortDirection.None);
SearchAllGameModes = new BoolSetting(iniFile, MULTIPLAYER, "SearchAllGameModes", false);

UseLegacyTunnels = new BoolSetting(iniFile, MULTIPLAYER, "UseLegacyTunnels", false);
UseDynamicTunnels = new BoolSetting(iniFile, MULTIPLAYER, "UseDynamicTunnels", true);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since these are mutually exclusive, making a single enum based (integer or string) TunnelMode setting instead could be a worthy idea. But this is OK too - doesn't significantly increase code complexity.


CheckForUpdates = new BoolSetting(iniFile, OPTIONS, "CheckforUpdates", true);

PrivacyPolicyAccepted = new BoolSetting(iniFile, OPTIONS, "PrivacyPolicyAccepted", false);
Expand Down Expand Up @@ -238,6 +241,9 @@ protected UserINISettings(IniFile iniFile)
public BoolSetting SteamIntegration { get; private set; }
public BoolSetting AllowGameInvitesFromFriendsOnly { get; private set; }

public BoolSetting UseLegacyTunnels { get; private set; }
public BoolSetting UseDynamicTunnels { get; private set; }

public BoolSetting NotifyOnUserListChange { get; private set; }

public BoolSetting DisablePrivateMessagePopups { get; private set; }
Expand Down
48 changes: 40 additions & 8 deletions DXMainClient/DXGUI/Generic/OptionPanels/CnCNetOptionsPanel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ public CnCNetOptionsPanel(WindowManager windowManager, UserINISettings iniSettin

XNAClientDropDown ddAllowPrivateMessagesFrom;

XNAClientCheckBox chkUseLegacyTunnels;
XNAClientCheckBox chkUseDynamicTunnels;

GameCollection gameCollection;

List<XNAClientCheckBox> followedGameChks = new List<XNAClientCheckBox>();
Expand Down Expand Up @@ -118,7 +121,7 @@ private void InitOptions()
chkPersistentMode.Name = nameof(chkPersistentMode);
chkPersistentMode.ClientRectangle = new Rectangle(
chkSkipLoginWindow.X,
chkSkipLoginWindow.Bottom + 12, 0, 0);
chkSkipLoginWindow.Bottom + 9, 0, 0);
chkPersistentMode.Text = "Stay connected outside of the CnCNet lobby".L10N("Client:DTAConfig:StayConnect");
chkPersistentMode.CheckedChanged += ChkPersistentMode_CheckedChanged;

Expand All @@ -128,7 +131,7 @@ private void InitOptions()
chkConnectOnStartup.Name = nameof(chkConnectOnStartup);
chkConnectOnStartup.ClientRectangle = new Rectangle(
chkSkipLoginWindow.X,
chkPersistentMode.Bottom + 12, 0, 0);
chkPersistentMode.Bottom + 9, 0, 0);
chkConnectOnStartup.Text = "Connect automatically on client startup".L10N("Client:DTAConfig:ConnectOnStart");
chkConnectOnStartup.AllowChecking = false;

Expand All @@ -138,7 +141,7 @@ private void InitOptions()
chkDiscordIntegration.Name = nameof(chkDiscordIntegration);
chkDiscordIntegration.ClientRectangle = new Rectangle(
chkSkipLoginWindow.X,
chkConnectOnStartup.Bottom + 12, 0, 0);
chkConnectOnStartup.Bottom + 9, 0, 0);
chkDiscordIntegration.Text = "Show detailed game info in Discord status".L10N("Client:DTAConfig:DiscordStatus");

if (ClientConfiguration.Instance.DiscordIntegrationGloballyDisabled)
Expand All @@ -157,7 +160,7 @@ private void InitOptions()
chkAllowGameInvitesFromFriendsOnly.Name = nameof(chkAllowGameInvitesFromFriendsOnly);
chkAllowGameInvitesFromFriendsOnly.ClientRectangle = new Rectangle(
chkDiscordIntegration.X,
chkDiscordIntegration.Bottom + 12, 0, 0);
chkDiscordIntegration.Bottom + 9, 0, 0);
chkAllowGameInvitesFromFriendsOnly.Text = "Only receive game invitations from friends".L10N("Client:DTAConfig:FriendsOnly");

AddChild(chkAllowGameInvitesFromFriendsOnly);
Expand All @@ -167,17 +170,35 @@ private void InitOptions()
chkSteamIntegration.Name = nameof(chkSteamIntegration);
chkSteamIntegration.ClientRectangle = new Rectangle(
chkAllowGameInvitesFromFriendsOnly.X,
chkAllowGameInvitesFromFriendsOnly.Bottom + 12, 0, 0);
chkAllowGameInvitesFromFriendsOnly.Bottom + 9, 0, 0);
chkSteamIntegration.Text = "Show the game being played in Steam".L10N("Client:DTAConfig:SteamStatus");

AddChild(chkSteamIntegration);

chkUseLegacyTunnels = new XNAClientCheckBox(WindowManager);
chkUseLegacyTunnels.Name = nameof(chkUseLegacyTunnels);
chkUseLegacyTunnels.ClientRectangle = new Rectangle(
chkSteamIntegration.X,
chkSteamIntegration.Bottom + 9, 0, 0);
chkUseLegacyTunnels.Text = "Use legacy tunnels when hosting".L10N("Client:DTAConfig:LegacyTunnels");
chkUseLegacyTunnels.CheckedChanged += ChkUseLegacyTunnels_CheckedChanged;

AddChild(chkUseLegacyTunnels);

chkUseDynamicTunnels = new XNAClientCheckBox(WindowManager);
chkUseDynamicTunnels.Name = nameof(chkUseDynamicTunnels);
chkUseDynamicTunnels.ClientRectangle = new Rectangle(
chkUseLegacyTunnels.X,
chkUseLegacyTunnels.Bottom + 9, 0, 0);
chkUseDynamicTunnels.Text = "Use dynamic tunnels when hosting".L10N("Client:DTAConfig:DynamicTunnels");
AddChild(chkUseDynamicTunnels);
}

private void InitAllowPrivateMessagesFromDropdown()
{
XNALabel lblAllPrivateMessagesFrom = new XNALabel(WindowManager);
lblAllPrivateMessagesFrom.Name = nameof(lblAllPrivateMessagesFrom);
lblAllPrivateMessagesFrom.Text = "Allow Private Messages From:".L10N("Client:DTAConfig:AllowPMFrom");
lblAllPrivateMessagesFrom.Text = "Allow private messages from:".L10N("Client:DTAConfig:AllowPMFrom");
lblAllPrivateMessagesFrom.ClientRectangle = new Rectangle(
chkDisablePrivateMessagePopup.X,
chkDisablePrivateMessagePopup.Bottom + 12, 165, 0);
Expand All @@ -187,8 +208,8 @@ private void InitAllowPrivateMessagesFromDropdown()
ddAllowPrivateMessagesFrom = new XNAClientDropDown(WindowManager);
ddAllowPrivateMessagesFrom.Name = nameof(ddAllowPrivateMessagesFrom);
ddAllowPrivateMessagesFrom.ClientRectangle = new Rectangle(
lblAllPrivateMessagesFrom.Right,
lblAllPrivateMessagesFrom.Y - 2, 110, 0);
lblAllPrivateMessagesFrom.Right - 110,
lblAllPrivateMessagesFrom.Y + 22, 110, 0);

ddAllowPrivateMessagesFrom.AddItem(new XNADropDownItem()
{
Expand Down Expand Up @@ -298,6 +319,11 @@ private void InitGameListPanel()
}
}

private void ChkUseLegacyTunnels_CheckedChanged(object sender, EventArgs e)
{
chkUseDynamicTunnels.AllowChecking = !chkUseLegacyTunnels.Checked;
}

private void ChkSkipLoginWindow_CheckedChanged(object sender, EventArgs e)
{
CheckConnectOnStartupAllowance();
Expand Down Expand Up @@ -334,6 +360,8 @@ public override void Load()
chkSkipLoginWindow.Checked = IniSettings.SkipConnectDialog;
chkPersistentMode.Checked = IniSettings.PersistentMode;
chkSteamIntegration.Checked = IniSettings.SteamIntegration;
chkUseLegacyTunnels.Checked = IniSettings.UseLegacyTunnels;
chkUseDynamicTunnels.Checked = IniSettings.UseDynamicTunnels;

chkDiscordIntegration.Checked = !ClientConfiguration.Instance.DiscordIntegrationGloballyDisabled
&& IniSettings.DiscordIntegration;
Expand All @@ -354,6 +382,8 @@ public override void Load()

chkBox.Checked = IniSettings.IsGameFollowed(chkBox.Name);
}

ChkUseLegacyTunnels_CheckedChanged(null, EventArgs.Empty);
}

public override bool Save()
Expand All @@ -370,6 +400,8 @@ public override bool Save()
IniSettings.SkipConnectDialog.Value = chkSkipLoginWindow.Checked;
IniSettings.PersistentMode.Value = chkPersistentMode.Checked;
IniSettings.SteamIntegration.Value = chkSteamIntegration.Checked;
IniSettings.UseLegacyTunnels.Value = chkUseLegacyTunnels.Checked;
IniSettings.UseDynamicTunnels.Value = chkUseDynamicTunnels.Checked;

if (!ClientConfiguration.Instance.DiscordIntegrationGloballyDisabled)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -265,12 +265,12 @@ public void OnJoined()
{
channel.SendCTCPMessage(FILE_HASH_CTCP_COMMAND + " " + fhc.GetCompleteHash(), QueuedMessageType.SYSTEM_MESSAGE, 10);

channel.SendCTCPMessage(TUNNEL_PING_CTCP_COMMAND + " " + tunnelHandler.CurrentTunnel.PingInMs, QueuedMessageType.SYSTEM_MESSAGE, 10);
channel.SendCTCPMessage(TUNNEL_PING_CTCP_COMMAND + " " + tunnelHandler.CurrentTunnel.Ping.Milliseconds, QueuedMessageType.SYSTEM_MESSAGE, 10);

if (tunnelHandler.CurrentTunnel.PingInMs < 0)
if (tunnelHandler.CurrentTunnel.Ping.IsUnknown())
AddNotice(string.Format("{0} - unknown ping to tunnel server.".L10N("Client:Main:PlayerUnknownPing"), ProgramConstants.PLAYERNAME));
else
AddNotice(string.Format("{0} - ping to tunnel server: {1} ms".L10N("Client:Main:PlayerPing"), ProgramConstants.PLAYERNAME, tunnelHandler.CurrentTunnel.PingInMs));
AddNotice(string.Format("{0} - ping to tunnel server: {1} ms".L10N("Client:Main:PlayerPing"), ProgramConstants.PLAYERNAME, tunnelHandler.CurrentTunnel.Ping.Milliseconds));
}

topBar.AddPrimarySwitchable(this);
Expand Down
59 changes: 12 additions & 47 deletions DXMainClient/DXGUI/Multiplayer/CnCNet/CnCNetLobby.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1543,9 +1543,17 @@ private void GameBroadcastChannel_CTCPReceived(object sender, ChannelCTCPEventAr
string mapName = splitMessage[7];
string gameMode = splitMessage[8];

string[] tunnelAddressAndPort = splitMessage[9].Split(':');
string tunnelAddress = tunnelAddressAndPort[0];
int tunnelPort = int.Parse(tunnelAddressAndPort[1]);
bool isDynamicTunnels = splitMessage[9] == "[DYN]";
CnCNetTunnel tunnel = null;
if (!isDynamicTunnels)
{
string[] tunnelAddressAndPort = splitMessage[9].Split(':');
string tunnelAddress = tunnelAddressAndPort[0];
int tunnelPort = int.Parse(tunnelAddressAndPort[1]);
tunnel = tunnelHandler.Tunnels.Find(t => t.Address == tunnelAddress && t.Port == tunnelPort);
if (tunnel == null)
return;
}

string loadedGameId = splitMessage[10];
int skillLevel = int.Parse(splitMessage[11]);
Expand All @@ -1556,51 +1564,8 @@ private void GameBroadcastChannel_CTCPReceived(object sender, ChannelCTCPEventAr
if (cncnetGame == null)
return;

// Find the tunnel server specified in the game message

if (tunnelHandler.Tunnels.Count == 0)
{
Logger.Log("Ignoring CTCP game message because there are no tunnels at all. Available tunnel count: 0. Is the connection to CnCNet HTTP service broken?");

// Remind users that the game is ignored because of no tunnel
if (lbGameList.Items.Count == 0 && lbGameList.HostedGames.Count == 0)
{
string message = ("There are no games listed. The client did receive a valid game message but can't add it to the list because there are no available tunnels. " +
"You can ignore this prompt if there are games listed later. Otherwise, it might indicate a network problem to CnCNet HTTP service.").L10N("Client:Main:NoTunnels");

if ((lbChatMessages.Items.LastOrDefault()?.Tag as ChatMessage)?.Message != message)
{
lbChatMessages.AddMessage(new ChatMessage(Color.Gray, message));
}
}

return;
}

CnCNetTunnel tunnel = tunnelHandler.Tunnels.Find(t => t.Address == tunnelAddress && t.Port == tunnelPort);

if (tunnel == null)
{
Logger.Log(string.Format("Ignoring CTCP game message because the specified tunnel {0}:{1} is not available. Available tunnel count: {2}",
tunnelAddress, tunnelPort, tunnelHandler.Tunnels.Count));

// Remind users that the game is ignored because of no specified tunnel
if (lbGameList.Items.Count == 0 && lbGameList.HostedGames.Count == 0)
{
string message = string.Format(("There are no games listed. The client did receive a valid game message but can't add it to the list because the specified tunnel is not available. " +
"You can ignore this prompt if there are games listed later. Otherwise, please contact support at {0}.").L10N("Client:Main:NoTunnelForGames"), ClientConfiguration.Instance.LongSupportURL);

if ((lbChatMessages.Items.LastOrDefault()?.Tag as ChatMessage)?.Message != message)
{
lbChatMessages.AddMessage(new ChatMessage(Color.Gray, message));
}
}

return;
}

HostedCnCNetGame game = new HostedCnCNetGame(gameRoomChannelName, revision, gameVersion, maxPlayers,
gameRoomDisplayName, isCustomPassword, true, players,
gameRoomDisplayName, isCustomPassword, !isDynamicTunnels, players,
e.UserName, mapName, gameMode, mapHash);
game.IsLoadedGame = isLoadedGame;
game.MatchID = loadedGameId;
Expand Down
65 changes: 57 additions & 8 deletions DXMainClient/DXGUI/Multiplayer/CnCNet/GameCreationWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public GameCreationWindow(WindowManager windowManager, TunnelHandler tunnelHandl
private XNALabel lblPassword;

private XNALabel lblTunnelServer;
private XNALabel lblDynamicTunnels;
private TunnelListBox lbTunnelList;

private XNAClientButton btnCreateGame;
Expand All @@ -53,6 +54,8 @@ public override void Initialize()
lbTunnelList = new TunnelListBox(WindowManager, tunnelHandler);
lbTunnelList.Name = nameof(lbTunnelList);

lbTunnelList.TargetVersion = UserINISettings.Instance.UseLegacyTunnels ? 2 : 3;

SkillLevelOptions = ClientConfiguration.Instance.SkillLevelOptions.Split(',');

Name = "GameCreationWindow";
Expand Down Expand Up @@ -136,6 +139,14 @@ public override void Initialize()
lblTunnelServer.Enabled = false;
lblTunnelServer.Visible = false;

lblDynamicTunnels = new XNALabel(WindowManager);
lblDynamicTunnels.Name = nameof(lblDynamicTunnels);
lblDynamicTunnels.ClientRectangle = new Rectangle(UIDesignConstants.EMPTY_SPACE_SIDES +
UIDesignConstants.CONTROL_HORIZONTAL_MARGIN, lblTunnelServer.Y, 0, 0);
lblDynamicTunnels.Text = "Dynamic tunnels are enabled. You can change this in the settings.".L10N("Client:Main:DynamicTunnelsInfo");
lblDynamicTunnels.Enabled = false;
lblDynamicTunnels.Visible = false;

lbTunnelList.X = UIDesignConstants.EMPTY_SPACE_SIDES +
UIDesignConstants.CONTROL_HORIZONTAL_MARGIN;
lbTunnelList.Y = lblTunnelServer.Bottom + UIDesignConstants.CONTROL_VERTICAL_MARGIN;
Expand Down Expand Up @@ -174,6 +185,7 @@ public override void Initialize()
AddChild(tbPassword);
AddChild(lblPassword);
AddChild(btnDisplayAdvancedOptions);
AddChild(lblDynamicTunnels);
AddChild(lblTunnelServer);
AddChild(lbTunnelList);
AddChild(btnCreateGame);
Expand Down Expand Up @@ -240,8 +252,7 @@ private void BtnLoadMPGame_LeftClick(object sender, EventArgs e)

GameCreationEventArgs ea = new GameCreationEventArgs(gameName,
spawnSGIni.GetIntValue("Settings", "PlayerCount", 2), password,
tunnelHandler.Tunnels[lbTunnelList.SelectedIndex], ddSkillLevel.SelectedIndex);

lbTunnelList.GetSelectedTunnel(), ddSkillLevel.SelectedIndex);
LoadedGameCreated?.Invoke(this, ea);
}

Expand All @@ -257,15 +268,17 @@ private void BtnCreateGame_LeftClick(object sender, EventArgs e)
return;
}

if (!lbTunnelList.IsValidIndexSelected())
CnCNetTunnel selectedTunnel = null;
if (!UserINISettings.Instance.UseDynamicTunnels)
{
return;
if (!lbTunnelList.IsValidIndexSelected())
return;
selectedTunnel = lbTunnelList.GetSelectedTunnel();
}

GameCreated?.Invoke(this,
new GameCreationEventArgs(gameName,int.Parse(ddMaxPlayers.SelectedItem.Text),
tbPassword.Text,tunnelHandler.Tunnels[lbTunnelList.SelectedIndex],
ddSkillLevel.SelectedIndex)
new GameCreationEventArgs(gameName, int.Parse(ddMaxPlayers.SelectedItem.Text),
tbPassword.Text, selectedTunnel, ddSkillLevel.SelectedIndex)
);
}

Expand All @@ -285,8 +298,15 @@ private void BtnDisplayAdvancedOptions_LeftClick(object sender, EventArgs e)

Height = btnCreateGame.Bottom + UIDesignConstants.CONTROL_VERTICAL_MARGIN + UIDesignConstants.EMPTY_SPACE_BOTTOM;

bool showTunnelList = ShouldShowTunnelList();
lblTunnelServer.Enable();
lbTunnelList.Enable();
lblTunnelServer.Visible = showTunnelList;

if (showTunnelList)
lbTunnelList.Enable();
else
lbTunnelList.Disable();

btnDisplayAdvancedOptions.Disable();

SetAttributesFromIni();
Expand All @@ -296,6 +316,26 @@ private void BtnDisplayAdvancedOptions_LeftClick(object sender, EventArgs e)

public void Refresh()
{
bool showTunnelList = ShouldShowTunnelList();
bool isAdvancedMode = Name == "GameCreationWindow_Advanced";

if (!showTunnelList)
{
lblDynamicTunnels.Visible = true;
lbTunnelList.Visible = false;
lblTunnelServer.Visible = false;
btnDisplayAdvancedOptions.Visible = false;
}
else
{
lblDynamicTunnels.Visible = false;
lbTunnelList.Visible = isAdvancedMode;
lblTunnelServer.Visible = isAdvancedMode;
btnDisplayAdvancedOptions.Visible = !isAdvancedMode;
}

lbTunnelList.TargetVersion = UserINISettings.Instance.UseLegacyTunnels ? 2 : 3;

btnLoadMPGame.AllowClick = AllowLoadingGame();
}

Expand All @@ -316,5 +356,14 @@ private bool AllowLoadingGame()

return true;
}

/// <summary>
/// Determines if the tunnel list should be shown.
/// The tunnel list is visible when legacy tunnels are enabled or dynamic tunnels are disabled.
/// </summary>
private bool ShouldShowTunnelList()
{
return UserINISettings.Instance.UseLegacyTunnels || !UserINISettings.Instance.UseDynamicTunnels;
}
}
}
Loading
Loading