From 9188da5681e6bcf851a1cf8528c4a5eae0aeff4f Mon Sep 17 00:00:00 2001 From: Sad Pencil Date: Tue, 3 Oct 2023 16:41:11 +0800 Subject: [PATCH] Make CnCNet URLs configurable --- ClientCore/ClientConfiguration.cs | 8 ++ DXMainClient/Domain/MainClientConstants.cs | 4 +- .../CnCNet/CnCNetPlayerCountTask.cs | 9 +- .../Domain/Multiplayer/CnCNet/MapSharer.cs | 8 +- .../Multiplayer/CnCNet/TunnelHandler.cs | 87 +++++++++++++------ 5 files changed, 82 insertions(+), 34 deletions(-) diff --git a/ClientCore/ClientConfiguration.cs b/ClientCore/ClientConfiguration.cs index 5f172d05e..74ba2406c 100644 --- a/ClientCore/ClientConfiguration.cs +++ b/ClientCore/ClientConfiguration.cs @@ -219,6 +219,14 @@ public void RefreshSettings() public string ManualDownloadURL => clientDefinitionsIni.GetStringValue(SETTINGS, "ManualDownloadURL", string.Empty); + public string CnCNetTunnelListURL => clientDefinitionsIni.GetStringValue(SETTINGS, "CnCNetTunnelListURL", "http://cncnet.org/master-list"); + + public string CnCNetPlayerCountURL => clientDefinitionsIni.GetStringValue(SETTINGS, "CnCNetPlayerCountURL", "http://api.cncnet.org/status"); + + public string CnCNetMapDBDownloadURL => clientDefinitionsIni.GetStringValue(SETTINGS, "CnCNetMapDBDownloadURL", "http://mapdb.cncnet.org"); + + public string CnCNetMapDBUploadURL => clientDefinitionsIni.GetStringValue(SETTINGS, "CnCNetMapDBUploadURL", "http://mapdb.cncnet.org/upload"); + public string FinalSunIniPath => SafePath.CombineFilePath(clientDefinitionsIni.GetStringValue(SETTINGS, "FSIniPath", SafePath.CombineFilePath("FinalSun", "FinalSun.ini"))); public int MaxNameLength => clientDefinitionsIni.GetIntValue(SETTINGS, "MaxNameLength", 16); diff --git a/DXMainClient/Domain/MainClientConstants.cs b/DXMainClient/Domain/MainClientConstants.cs index 0197f113f..0013fd644 100644 --- a/DXMainClient/Domain/MainClientConstants.cs +++ b/DXMainClient/Domain/MainClientConstants.cs @@ -4,7 +4,7 @@ namespace DTAClient.Domain { public static class MainClientConstants { - public const string CNCNET_TUNNEL_LIST_URL = "http://cncnet.org/master-list"; + public static string CNCNET_TUNNEL_LIST_URL = "http://cncnet.org/master-list"; public static string GAME_NAME_LONG = "CnCNet Client"; public static string GAME_NAME_SHORT = "CnCNet"; @@ -33,6 +33,8 @@ public static void Initialize() CREDITS_URL = clientConfiguration.CreditsURL; + CNCNET_TUNNEL_LIST_URL = clientConfiguration.CnCNetTunnelListURL; + USE_ISOMETRIC_CELLS = clientConfiguration.UseIsometricCells; TDRA_WAYPOINT_COEFFICIENT = clientConfiguration.WaypointCoefficient; MAP_CELL_SIZE_X = clientConfiguration.MapCellSizeX; diff --git a/DXMainClient/Domain/Multiplayer/CnCNet/CnCNetPlayerCountTask.cs b/DXMainClient/Domain/Multiplayer/CnCNet/CnCNetPlayerCountTask.cs index 0bf357b90..b417dd1d9 100644 --- a/DXMainClient/Domain/Multiplayer/CnCNet/CnCNetPlayerCountTask.cs +++ b/DXMainClient/Domain/Multiplayer/CnCNet/CnCNetPlayerCountTask.cs @@ -50,10 +50,15 @@ private static int GetCnCNetPlayerCount() { try { + // Don't fetch the player count if it is explicitly disabled + // For example, the official CnCNet server might be unavailable/unstable in a country with Internet censorship, + // which causes lags in the splash screen. In the worst case, say if packets are dropped, it waits until timeouts --- 30 seconds + if (string.IsNullOrWhiteSpace(ClientConfiguration.Instance.CnCNetPlayerCountURL)) + return -1; + WebClient client = new WebClient(); + Stream data = client.OpenRead(ClientConfiguration.Instance.CnCNetPlayerCountURL); - Stream data = client.OpenRead("http://api.cncnet.org/status"); - string info = string.Empty; using (StreamReader reader = new StreamReader(data)) diff --git a/DXMainClient/Domain/Multiplayer/CnCNet/MapSharer.cs b/DXMainClient/Domain/Multiplayer/CnCNet/MapSharer.cs index 870dee82d..a9fe6de64 100644 --- a/DXMainClient/Domain/Multiplayer/CnCNet/MapSharer.cs +++ b/DXMainClient/Domain/Multiplayer/CnCNet/MapSharer.cs @@ -36,7 +36,7 @@ public static class MapSharer private static readonly object locker = new object(); - private const string MAPDB_URL = "http://mapdb.cncnet.org/upload"; + private static string MAPDB_URL => ClientConfiguration.Instance.CnCNetMapDBUploadURL; /// /// Adds a map into the CnCNet map upload queue. @@ -382,10 +382,12 @@ private static string DownloadMain(string sha1, string myGame, string mapName, o { webClient.Proxy = null; + string url = string.Format(CultureInfo.InvariantCulture, "{0}/{1}/{2}.zip", ClientConfiguration.Instance.CnCNetMapDBDownloadURL, myGame, sha1); + try { - Logger.Log("MapSharer: Downloading URL: " + "http://mapdb.cncnet.org/" + myGame + "/" + sha1 + ".zip"); - webClient.DownloadFile("http://mapdb.cncnet.org/" + myGame + "/" + sha1 + ".zip", destinationFile.FullName); + Logger.Log($"MapSharer: Downloading URL: {url}"); + webClient.DownloadFile(url, destinationFile.FullName); } catch (Exception ex) { diff --git a/DXMainClient/Domain/Multiplayer/CnCNet/TunnelHandler.cs b/DXMainClient/Domain/Multiplayer/CnCNet/TunnelHandler.cs index 59b3d2f49..73d0b5783 100644 --- a/DXMainClient/Domain/Multiplayer/CnCNet/TunnelHandler.cs +++ b/DXMainClient/Domain/Multiplayer/CnCNet/TunnelHandler.cs @@ -143,48 +143,78 @@ private Task PingCurrentTunnelAsync(bool checkTunnelList = false) }); } - /// - /// Downloads and parses the list of CnCNet tunnels. - /// - /// A list of tunnel servers. - private List RefreshTunnels() - { - FileInfo tunnelCacheFile = SafePath.GetFile(ProgramConstants.ClientUserFilesPath, "tunnel_cache"); - - List returnValue = new List(); + private bool IsOnlineTunnelDataAvailable() => !string.IsNullOrWhiteSpace(MainClientConstants.CNCNET_TUNNEL_LIST_URL); + private bool IsOfflineTunnelDataAvailable() => SafePath.GetFile(ProgramConstants.ClientUserFilesPath, "tunnel_cache").Exists; + private byte[] GetRawTunnelDataOnline() + { WebClient client = new WebClient(); + return client.DownloadData(MainClientConstants.CNCNET_TUNNEL_LIST_URL); + } - byte[] data; + private byte[] GetRawTunnelDataOffline() + { + FileInfo tunnelCacheFile = SafePath.GetFile(ProgramConstants.ClientUserFilesPath, "tunnel_cache"); + return File.ReadAllBytes(tunnelCacheFile.FullName); + } + private byte[] GetRawTunnelData(int retryCount = 2) + { Logger.Log("Fetching tunnel server info."); - try - { - data = client.DownloadData(MainClientConstants.CNCNET_TUNNEL_LIST_URL); - } - catch (Exception ex) + if (IsOnlineTunnelDataAvailable()) { - Logger.Log("Error when downloading tunnel server info: " + ex.Message); - Logger.Log("Retrying."); - try + for (int i = 0; i < retryCount; i++) { - data = client.DownloadData(MainClientConstants.CNCNET_TUNNEL_LIST_URL); - } - catch - { - if (!tunnelCacheFile.Exists) + try { - Logger.Log("Tunnel cache file doesn't exist!"); - return returnValue; + byte[] data = GetRawTunnelDataOnline(); + return data; } - else + catch (Exception ex) { - Logger.Log("Fetching tunnel server list failed. Using cached tunnel data."); - data = File.ReadAllBytes(tunnelCacheFile.FullName); + Logger.Log("Error when downloading tunnel server info: " + ex.Message); + if (i < retryCount) + Logger.Log("Retrying."); + else + Logger.Log("Fetching tunnel server list failed."); } } } + else + { + // Don't fetch the latest tunnel list if it is explicitly disabled + // For example, the official CnCNet server might be unavailable/unstable in a country with Internet censorship, + // where players might either establish a substitute server or manually distribute the tunnel cache file + Logger.Log("Fetching tunnel server list online is disabled."); + } + + if (IsOfflineTunnelDataAvailable()) + { + Logger.Log("Using cached tunnel data."); + byte[] data = GetRawTunnelDataOffline(); + return data; + } + else + Logger.Log("Tunnel cache file doesn't exist!"); + + return null; + } + + + /// + /// Downloads and parses the list of CnCNet tunnels. + /// + /// A list of tunnel servers. + private List RefreshTunnels() + { + List returnValue = new List(); + + FileInfo tunnelCacheFile = SafePath.GetFile(ProgramConstants.ClientUserFilesPath, "tunnel_cache"); + + byte[] data = GetRawTunnelData(); + if (data is null) + return returnValue; string convertedData = Encoding.Default.GetString(data); @@ -234,6 +264,7 @@ private List RefreshTunnels() } } + Logger.Log($"Successfully refreshed tunnel cache with {returnValue.Count} servers."); return returnValue; }