diff --git a/PugSharp.Config/ServerConfig.cs b/PugSharp.Config/ServerConfig.cs index 09fed96..f95dd64 100644 --- a/PugSharp.Config/ServerConfig.cs +++ b/PugSharp.Config/ServerConfig.cs @@ -9,4 +9,10 @@ public class ServerConfig [JsonPropertyName("allow_players_without_match")] public bool AllowPlayersWithoutMatch { get; init; } = true; + + [JsonPropertyName("autoload_config")] + public string AutoloadConfig { get; init; } = string.Empty; + + [JsonPropertyName("autoload_config_auth_token")] + public string AutoloadConfigAuthToken { get; init; } = string.Empty; } diff --git a/PugSharp.Tests/ApplicationTests.cs b/PugSharp.Tests/ApplicationTests.cs index 8552051..a1f7254 100644 --- a/PugSharp.Tests/ApplicationTests.cs +++ b/PugSharp.Tests/ApplicationTests.cs @@ -45,4 +45,26 @@ public void InitializeApplicationTest() application.Initialize(hotReload: false); } + + [Fact] + public void ServerConfigHasAutoloadProperties() + { + var serverConfig = new ServerConfig + { + AutoloadConfig = "https://example.com/config.json", + AutoloadConfigAuthToken = "test-token" + }; + + Assert.Equal("https://example.com/config.json", serverConfig.AutoloadConfig); + Assert.Equal("test-token", serverConfig.AutoloadConfigAuthToken); + } + + [Fact] + public void ServerConfigDefaultsToEmptyAutoloadConfig() + { + var serverConfig = new ServerConfig(); + + Assert.Equal(string.Empty, serverConfig.AutoloadConfig); + Assert.Equal(string.Empty, serverConfig.AutoloadConfigAuthToken); + } } \ No newline at end of file diff --git a/PugSharp.Tests/ServerConfigTests.cs b/PugSharp.Tests/ServerConfigTests.cs new file mode 100644 index 0000000..1ffafc0 --- /dev/null +++ b/PugSharp.Tests/ServerConfigTests.cs @@ -0,0 +1,53 @@ +using System.Text.Json; + +using PugSharp.Config; + +namespace PugSharp.Tests; + +public class ServerConfigTests +{ + [Fact] + public void ServerConfigCanBeSerializedAndDeserialized() + { + var originalConfig = new ServerConfig + { + Locale = "en", + AllowPlayersWithoutMatch = true, + AutoloadConfig = "https://example.com/config.json", + AutoloadConfigAuthToken = "test-token" + }; + + var json = JsonSerializer.Serialize(originalConfig); + var deserializedConfig = JsonSerializer.Deserialize(json); + + Assert.NotNull(deserializedConfig); + Assert.Equal(originalConfig.Locale, deserializedConfig.Locale); + Assert.Equal(originalConfig.AllowPlayersWithoutMatch, deserializedConfig.AllowPlayersWithoutMatch); + Assert.Equal(originalConfig.AutoloadConfig, deserializedConfig.AutoloadConfig); + Assert.Equal(originalConfig.AutoloadConfigAuthToken, deserializedConfig.AutoloadConfigAuthToken); + } + + [Fact] + public void ServerConfigJsonPropertyNamesAreCorrect() + { + var config = new ServerConfig + { + AutoloadConfig = "test-config", + AutoloadConfigAuthToken = "test-token" + }; + + var json = JsonSerializer.Serialize(config); + + Assert.Contains("\"autoload_config\"", json, StringComparison.Ordinal); + Assert.Contains("\"autoload_config_auth_token\"", json, StringComparison.Ordinal); + } + + [Fact] + public void ServerConfigDefaultsToEmptyAutoloadConfig() + { + var serverConfig = new ServerConfig(); + + Assert.Equal(string.Empty, serverConfig.AutoloadConfig); + Assert.Equal(string.Empty, serverConfig.AutoloadConfigAuthToken); + } +} \ No newline at end of file diff --git a/PugSharp/Application.cs b/PugSharp/Application.cs index 35bcf69..079244e 100644 --- a/PugSharp/Application.cs +++ b/PugSharp/Application.cs @@ -352,6 +352,11 @@ private void OnMapStartHandler(string mapName) SetMatchVariable(); }); } + else if (_Match == null && _ServerConfig != null && !string.IsNullOrEmpty(_ServerConfig.AutoloadConfig)) + { + _Logger.LogInformation("Map started, attempting to autoload config: {Config}", _ServerConfig.AutoloadConfig); + _ = Task.Run(() => TryAutoloadConfig()); + } } // TODO Add Round Events to RoundService? @@ -2024,6 +2029,74 @@ private void InitializeMatch(MatchInfo matchInfo, string roundBackupFile) KickNonMatchPlayers(); } + private async Task TryAutoloadConfig() + { + if (_ServerConfig == null || string.IsNullOrEmpty(_ServerConfig.AutoloadConfig)) + { + return; + } + + if (_Match != null) + { + _Logger.LogInformation("Match is already running, skipping autoload"); + return; + } + + _Logger.LogInformation("Attempting to autoload config: {Config}", _ServerConfig.AutoloadConfig); + + try + { + var config = _ServerConfig.AutoloadConfig; + var authToken = _ServerConfig.AutoloadConfigAuthToken; + + // Check if it's a URL or file path + if (Uri.TryCreate(config, UriKind.Absolute, out var uri) && + (uri.Scheme.Equals(Uri.UriSchemeHttp, StringComparison.Ordinal) || uri.Scheme.Equals(Uri.UriSchemeHttps, StringComparison.Ordinal))) + { + // Load from URL + var result = await _ConfigProvider.LoadMatchConfigFromUrlAsync(config, authToken).ConfigureAwait(false); + result.Switch( + error => + { + _Logger.LogError("Failed to autoload config from URL: {Error}", error.Value); + }, + matchConfig => + { + _Logger.LogInformation("Successfully autoloaded config from URL"); + + // Use same token for APIstats if there's no token set in the matchconfig + if (string.IsNullOrEmpty(matchConfig.EventulaApistatsToken)) + { + matchConfig.EventulaApistatsToken = authToken; + } + + StoreConfig(matchConfig); + InitializeMatch(matchConfig); + }); + } + else + { + // Load from file + var result = await _ConfigProvider.LoadMatchConfigFromFileAsync(config).ConfigureAwait(false); + result.Switch( + error => + { + _Logger.LogError("Failed to autoload config from file: {Error}", error.Value); + }, + matchConfig => + { + _Logger.LogInformation("Successfully autoloaded config from file"); + StoreConfig(matchConfig); + InitializeMatch(matchConfig); + }); + } + } + catch (Exception ex) + { + _Logger.LogError(ex, "Error during autoload config"); + } + } + private void OnMatchFinalized(object? sender, MatchFinalizedEventArgs e) { StopMatch();