@@ -18,7 +18,7 @@ public static class ConfigValidator
1818 /// If the config is invalid, the reasons are logged.
1919 /// </summary>
2020 /// <returns>Whether the given match is valid and can be started without issues.</returns>
21- public static bool Validate ( MatchConfigurationT config )
21+ public static bool Validate ( MatchConfigurationT config , bool surpressWarnings = false )
2222 {
2323 bool valid = true ;
2424 PsyonixLoadouts . Reset ( ) ;
@@ -48,16 +48,21 @@ public static bool Validate(MatchConfigurationT config)
4848 config . PlayerConfigurations ??= new ( ) ;
4949 config . ScriptConfigurations ??= new ( ) ;
5050
51- valid = ValidatePlayers ( ctx , config . PlayerConfigurations ) && valid ;
52- valid = ValidateScripts ( ctx , config . ScriptConfigurations ) && valid ;
51+ Dictionary < string , ( string rootDir , string runCmd ) > agentIdTracker = new ( ) ;
52+ valid =
53+ ValidatePlayers ( ctx , config . PlayerConfigurations , agentIdTracker , surpressWarnings )
54+ && valid ;
55+ valid = ValidateScripts ( ctx , config . ScriptConfigurations , agentIdTracker ) && valid ;
5356
5457 Logger . LogDebug ( valid ? "Match config is valid." : "Match config is invalid!" ) ;
5558 return valid ;
5659 }
5760
5861 private static bool ValidatePlayers (
5962 ConfigContextTracker ctx ,
60- List < PlayerConfigurationT > players
63+ List < PlayerConfigurationT > players ,
64+ Dictionary < string , ( string rootDir , string runCmd ) > agentIdTracker ,
65+ bool surpressWarnings
6166 )
6267 {
6368 bool valid = true ;
@@ -99,6 +104,46 @@ List<PlayerConfigurationT> players
99104 bot . Loadout . LoadoutPaint ??= new ( ) ;
100105
101106 player . PlayerId = $ "{ bot . AgentId } /{ player . Team } /{ i } ". GetHashCode ( ) ;
107+
108+ // Dont validate agent id for bots that will be manually started
109+ if ( ! surpressWarnings && ! string . IsNullOrEmpty ( bot . RunCommand ) )
110+ {
111+ // Reduce user confusion around how agent ids should be used
112+ // Same bot == same agent id, different bot == different agent id
113+ // This is not a hard requirement, so we just log a warning
114+ // We check for "same bot" by comparing RootDir and RunCommand
115+ if ( agentIdTracker . TryGetValue ( bot . AgentId , out var existing ) )
116+ {
117+ if (
118+ existing . rootDir != bot . RootDir
119+ || existing . runCmd != bot . RunCommand
120+ )
121+ {
122+ string errorStr ;
123+
124+ if ( existing . rootDir != bot . RootDir )
125+ {
126+ errorStr =
127+ existing . runCmd != bot . RunCommand
128+ ? "RootDirs and RunCommands"
129+ : "RootDirs" ;
130+ }
131+ else
132+ {
133+ errorStr = "RunCommands" ;
134+ }
135+
136+ Logger . LogWarning (
137+ $ "Potential agent ID conflict: \" { bot . AgentId } \" is used by multiple bots with different { errorStr } .\n "
138+ + "Agent configs using the same ID may get used interchangeably. Agents that behave differently should have unique IDs."
139+ ) ;
140+ }
141+ }
142+ else
143+ {
144+ agentIdTracker [ bot . AgentId ] = ( bot . RootDir , bot . RunCommand ) ;
145+ }
146+ }
102147 break ;
103148 case PsyonixBotT bot :
104149 string skill = bot . BotSkill switch
@@ -168,7 +213,8 @@ List<PlayerConfigurationT> players
168213
169214 private static bool ValidateScripts (
170215 ConfigContextTracker ctx ,
171- List < ScriptConfigurationT > scripts
216+ List < ScriptConfigurationT > scripts ,
217+ Dictionary < string , ( string rootDir , string runCmd ) > agentIdTracker
172218 )
173219 {
174220 bool valid = true ;
@@ -192,6 +238,19 @@ List<ScriptConfigurationT> scripts
192238 script . RunCommand ??= "" ;
193239 script . RootDir ??= "" ;
194240 script . ScriptId = $ "{ script . AgentId } /{ Team . Scripts } /{ i } ". GetHashCode ( ) ;
241+
242+ if ( agentIdTracker . TryGetValue ( script . AgentId , out var existing ) )
243+ {
244+ Logger . LogError (
245+ $ "{ ctx . ToStringWithEnd ( Fields . AgentAgentId ) } \" { script . AgentId } \" is already in use. "
246+ + "Each script must have a unique agent ID."
247+ ) ;
248+ valid = false ;
249+ }
250+ else
251+ {
252+ agentIdTracker [ script . AgentId ] = ( script . RootDir , script . RunCommand ) ;
253+ }
195254 }
196255
197256 return valid ;
0 commit comments