From 0b8210332a62158b04a5d489c953d574a782b04b Mon Sep 17 00:00:00 2001 From: VirxEC Date: Wed, 26 Nov 2025 16:45:55 -0500 Subject: [PATCH 1/5] Validate AgentIDs in ConfigValidator --- RLBotCS/Main.cs | 2 +- RLBotCS/ManagerTools/ConfigValidator.cs | 61 ++++++++++++++++++++-- RLBotCS/Server/ServerMessage/StartMatch.cs | 2 +- 3 files changed, 60 insertions(+), 5 deletions(-) diff --git a/RLBotCS/Main.cs b/RLBotCS/Main.cs index f1e2f76..c3cd144 100644 --- a/RLBotCS/Main.cs +++ b/RLBotCS/Main.cs @@ -10,7 +10,7 @@ if (args.Length > 0 && args[0] == "--version") { Console.WriteLine( - "RLBotServer v5.beta.7.10\n" + "RLBotServer v5.beta.7.11\n" + $"Bridge {BridgeVersion.Version}\n" + "@ https://www.rlbot.org & https://github.com/RLBot/core" ); diff --git a/RLBotCS/ManagerTools/ConfigValidator.cs b/RLBotCS/ManagerTools/ConfigValidator.cs index ce198e8..f7f22a9 100644 --- a/RLBotCS/ManagerTools/ConfigValidator.cs +++ b/RLBotCS/ManagerTools/ConfigValidator.cs @@ -18,7 +18,7 @@ public static class ConfigValidator /// If the config is invalid, the reasons are logged. /// /// Whether the given match is valid and can be started without issues. - public static bool Validate(MatchConfigurationT config) + public static bool Validate(MatchConfigurationT config, bool surpressWarnings = false) { bool valid = true; PsyonixLoadouts.Reset(); @@ -48,7 +48,7 @@ public static bool Validate(MatchConfigurationT config) config.PlayerConfigurations ??= new(); config.ScriptConfigurations ??= new(); - valid = ValidatePlayers(ctx, config.PlayerConfigurations) && valid; + valid = ValidatePlayers(ctx, config.PlayerConfigurations, surpressWarnings) && valid; valid = ValidateScripts(ctx, config.ScriptConfigurations) && valid; Logger.LogDebug(valid ? "Match config is valid." : "Match config is invalid!"); @@ -57,13 +57,17 @@ public static bool Validate(MatchConfigurationT config) private static bool ValidatePlayers( ConfigContextTracker ctx, - List players + List players, + bool surpressWarnings ) { bool valid = true; int humanCount = 0; int humanIndex = -1; + // map of agentid -> rootdir,runcmd + Dictionary agentIdTracker = new(); + for (int i = 0; i < players.Count; i++) { using var _ = ctx.Begin($"{Fields.CarsList}[{i}]"); @@ -99,6 +103,46 @@ List players bot.Loadout.LoadoutPaint ??= new(); player.PlayerId = $"{bot.AgentId}/{player.Team}/{i}".GetHashCode(); + + // Dont validate agent id for bots that will be manually started + if (!surpressWarnings && !string.IsNullOrEmpty(bot.RunCommand)) + { + // Reduce user confusion around how agent ids should be used + // Same bot == same agent id, different bot == different agent id + // This is not a hard requirement, so we just log a warning + // We check for "same bot" by comparing RootDir and RunCommand + if (agentIdTracker.TryGetValue(bot.AgentId, out var existing)) + { + if ( + existing.rootDir != bot.RootDir + || existing.runCmd != bot.RunCommand + ) + { + string errorStr; + + if (existing.rootDir != bot.RootDir) + { + errorStr = + existing.runCmd != bot.RunCommand + ? "RootDirs and RunCommands" + : "RootDirs"; + } + else + { + errorStr = "RunCommands"; + } + + Logger.LogWarning( + $"Potential agent ID conflict: {bot.AgentId} is used by multiple bots with different {errorStr}.\n" + + "Agent configs using the same ID may get used interchangeably. Agents that behave differently should have unique IDs." + ); + } + } + else + { + agentIdTracker[bot.AgentId] = (bot.RootDir, bot.RunCommand); + } + } break; case PsyonixBotT bot: string skill = bot.BotSkill switch @@ -172,6 +216,7 @@ List scripts ) { bool valid = true; + HashSet agentIds = new(); for (int i = 0; i < scripts.Count; i++) { @@ -192,6 +237,16 @@ List scripts script.RunCommand ??= ""; script.RootDir ??= ""; script.ScriptId = $"{script.AgentId}/{Team.Scripts}/{i}".GetHashCode(); + + // Scripts must have unique agent ids + if (!agentIds.Add(script.AgentId)) + { + Logger.LogError( + $"{ctx.ToStringWithEnd(Fields.AgentAgentId)} \"{script.AgentId}\" is already in use. " + + "Each script must have a unique agent ID." + ); + valid = false; + } } return valid; diff --git a/RLBotCS/Server/ServerMessage/StartMatch.cs b/RLBotCS/Server/ServerMessage/StartMatch.cs index 361cf9d..94c068f 100644 --- a/RLBotCS/Server/ServerMessage/StartMatch.cs +++ b/RLBotCS/Server/ServerMessage/StartMatch.cs @@ -9,7 +9,7 @@ readonly struct StartMatch(MatchConfigurationT MatchConfig) : IServerMessage { public ServerAction Execute(ServerContext context) { - Debug.Assert(ConfigValidator.Validate(MatchConfig)); + Debug.Assert(ConfigValidator.Validate(MatchConfig, true)); context.Bridge.TryWrite(new ClearRenders()); From a7b7c42181dade45e50f4587efff715ed4b5b578 Mon Sep 17 00:00:00 2001 From: VirxEC Date: Wed, 26 Nov 2025 16:50:30 -0500 Subject: [PATCH 2/5] Track AgentIDs across bots and scripts --- RLBotCS/ManagerTools/ConfigValidator.cs | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/RLBotCS/ManagerTools/ConfigValidator.cs b/RLBotCS/ManagerTools/ConfigValidator.cs index f7f22a9..6b9d3a7 100644 --- a/RLBotCS/ManagerTools/ConfigValidator.cs +++ b/RLBotCS/ManagerTools/ConfigValidator.cs @@ -48,8 +48,11 @@ public static bool Validate(MatchConfigurationT config, bool surpressWarnings = config.PlayerConfigurations ??= new(); config.ScriptConfigurations ??= new(); - valid = ValidatePlayers(ctx, config.PlayerConfigurations, surpressWarnings) && valid; - valid = ValidateScripts(ctx, config.ScriptConfigurations) && valid; + Dictionary agentIdTracker = new(); + valid = + ValidatePlayers(ctx, config.PlayerConfigurations, agentIdTracker, surpressWarnings) + && valid; + valid = ValidateScripts(ctx, config.ScriptConfigurations, agentIdTracker) && valid; Logger.LogDebug(valid ? "Match config is valid." : "Match config is invalid!"); return valid; @@ -58,6 +61,7 @@ public static bool Validate(MatchConfigurationT config, bool surpressWarnings = private static bool ValidatePlayers( ConfigContextTracker ctx, List players, + Dictionary agentIdTracker, bool surpressWarnings ) { @@ -65,9 +69,6 @@ bool surpressWarnings int humanCount = 0; int humanIndex = -1; - // map of agentid -> rootdir,runcmd - Dictionary agentIdTracker = new(); - for (int i = 0; i < players.Count; i++) { using var _ = ctx.Begin($"{Fields.CarsList}[{i}]"); @@ -212,11 +213,11 @@ bool surpressWarnings private static bool ValidateScripts( ConfigContextTracker ctx, - List scripts + List scripts, + Dictionary agentIdTracker ) { bool valid = true; - HashSet agentIds = new(); for (int i = 0; i < scripts.Count; i++) { @@ -238,14 +239,16 @@ List scripts script.RootDir ??= ""; script.ScriptId = $"{script.AgentId}/{Team.Scripts}/{i}".GetHashCode(); - // Scripts must have unique agent ids - if (!agentIds.Add(script.AgentId)) + if (agentIdTracker.TryGetValue(script.AgentId, out var existing)) { Logger.LogError( $"{ctx.ToStringWithEnd(Fields.AgentAgentId)} \"{script.AgentId}\" is already in use. " + "Each script must have a unique agent ID." ); - valid = false; + } + else + { + agentIdTracker[script.AgentId] = (script.RootDir, script.RunCommand); } } From 5178f9a60dff85dd5fc3fddf34230fc5ee8af37e Mon Sep 17 00:00:00 2001 From: Eric Veilleux Date: Sun, 30 Nov 2025 04:03:53 -0500 Subject: [PATCH 3/5] Update RLBotCS/ManagerTools/ConfigValidator.cs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Nicolaj 'Eastvillage' Ø Jensen --- RLBotCS/ManagerTools/ConfigValidator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RLBotCS/ManagerTools/ConfigValidator.cs b/RLBotCS/ManagerTools/ConfigValidator.cs index 6b9d3a7..eff3b7b 100644 --- a/RLBotCS/ManagerTools/ConfigValidator.cs +++ b/RLBotCS/ManagerTools/ConfigValidator.cs @@ -134,7 +134,7 @@ bool surpressWarnings } Logger.LogWarning( - $"Potential agent ID conflict: {bot.AgentId} is used by multiple bots with different {errorStr}.\n" + $"Potential agent ID conflict: \"{bot.AgentId}\" is used by multiple bots with different {errorStr}.\n" + "Agent configs using the same ID may get used interchangeably. Agents that behave differently should have unique IDs." ); } From 11d7c45ff6b9e62da3763ebb77816519dccac3e7 Mon Sep 17 00:00:00 2001 From: VirxEC Date: Sun, 30 Nov 2025 04:05:29 -0500 Subject: [PATCH 4/5] Ensure config is invalidated upon dup'd script aid --- RLBotCS/ManagerTools/ConfigValidator.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/RLBotCS/ManagerTools/ConfigValidator.cs b/RLBotCS/ManagerTools/ConfigValidator.cs index eff3b7b..e0f9a20 100644 --- a/RLBotCS/ManagerTools/ConfigValidator.cs +++ b/RLBotCS/ManagerTools/ConfigValidator.cs @@ -245,6 +245,7 @@ private static bool ValidateScripts( $"{ctx.ToStringWithEnd(Fields.AgentAgentId)} \"{script.AgentId}\" is already in use. " + "Each script must have a unique agent ID." ); + valid = false; } else { From 99e17a70011fbecaf74676b27b2cd61dc2e3b0e3 Mon Sep 17 00:00:00 2001 From: VirxEC Date: Sun, 30 Nov 2025 04:07:25 -0500 Subject: [PATCH 5/5] Update version --- RLBotCS/Main.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RLBotCS/Main.cs b/RLBotCS/Main.cs index c3cd144..e06296e 100644 --- a/RLBotCS/Main.cs +++ b/RLBotCS/Main.cs @@ -10,7 +10,7 @@ if (args.Length > 0 && args[0] == "--version") { Console.WriteLine( - "RLBotServer v5.beta.7.11\n" + "RLBotServer v5.0.0-rc.1\n" + $"Bridge {BridgeVersion.Version}\n" + "@ https://www.rlbot.org & https://github.com/RLBot/core" );