@@ -90,7 +90,18 @@ public void RefreshSettings()
9090
9191 #region Client settings
9292
93- public string MainMenuMusicName => SafePath . CombineFilePath ( DTACnCNetClient_ini . GetStringValue ( GENERAL , "MainMenuTheme" , "mainmenu" ) ) ;
93+ private string _mainMenuMusicName = null ;
94+ public string MainMenuMusicName => _mainMenuMusicName ??= GetMainMenuMusicName ( ) ;
95+ private string GetMainMenuMusicName ( )
96+ {
97+ string raw = DTACnCNetClient_ini . GetStringValue ( GENERAL , "MainMenuTheme" , "mainmenu" ) ;
98+ string [ ] parts = raw . SplitWithCleanup ( ) ;
99+ string chosen = parts . Length > 0
100+ ? parts [ new Random ( ) . Next ( parts . Length ) ]
101+ : "mainmenu" ;
102+
103+ return SafePath . CombineFilePath ( chosen ) ;
104+ }
94105
95106 public float DefaultAlphaRate => DTACnCNetClient_ini . GetSingleValue ( GENERAL , "AlphaRate" , 0.005f ) ;
96107
@@ -258,13 +269,17 @@ public void RefreshSettings()
258269
259270 public bool UseBuiltStatistic => clientDefinitionsIni . GetBooleanValue ( SETTINGS , "UseBuiltStatistic" , false ) ;
260271
272+ public string WindowedModeKey => clientDefinitionsIni . GetStringValue ( SETTINGS , "WindowedModeKey" , "Video.Windowed" ) ;
273+
261274 public bool CopyResolutionDependentLanguageDLL => clientDefinitionsIni . GetBooleanValue ( SETTINGS , "CopyResolutionDependentLanguageDLL" , true ) ;
262275
263276 public string StatisticsLogFileName => clientDefinitionsIni . GetStringValue ( SETTINGS , "StatisticsLogFileName" , "DTA.LOG" ) ;
264277
265278 public string [ ] TrustedDomains => clientDefinitionsIni . GetStringListValue ( SETTINGS , "TrustedDomains" , string . Empty ) ;
266279
267- public string [ ] AlwaysTrustedDomains = { "cncnet.org" , "gamesurge.net" , "dronebl.org" , "discord.com" , "discord.gg" , "youtube.com" , "youtu.be" } ;
280+ public string [ ] AlwaysTrustedDomains = { "cncnet.org" , "gamesurge.net" , "dronebl.org" , "discord.com" , "discord.gg" , "youtube.com" , "youtu.be" } ;
281+
282+ public bool ShowGameIconInGameList => clientDefinitionsIni . GetBooleanValue ( SETTINGS , "ShowGameIconInGameList" , true ) ;
268283
269284 public ( string Name , string Path ) GetThemeInfoFromIndex ( int themeIndex ) => clientDefinitionsIni . GetStringValue ( "Themes" , themeIndex . ToString ( ) , "," ) . Split ( ',' ) . AsTuple2 ( ) ;
270285
@@ -369,9 +384,13 @@ private List<TranslationGameFile> ParseTranslationGameFiles()
369384 public bool InactiveHostKickEnabled => InactiveHostWarningMessageSeconds > 0 && InactiveHostKickSeconds > 0 ;
370385
371386 public string SkillLevelOptions => clientDefinitionsIni . GetStringValue ( SETTINGS , "SkillLevelOptions" , "Any,Beginner,Intermediate,Pro" ) ;
372-
387+
373388 public int DefaultSkillLevelIndex => clientDefinitionsIni . GetIntValue ( SETTINGS , "DefaultSkillLevelIndex" , 0 ) ;
374-
389+
390+ public bool CampaignTagSelectorEnabled => clientDefinitionsIni . GetBooleanValue ( SETTINGS , "CampaignTagSelectorEnabled" , false ) ;
391+
392+ public bool ReturnToMainMenuOnMissionLaunch => clientDefinitionsIni . GetBooleanValue ( SETTINGS , "ReturnToMainMenuOnMissionLaunch" , true ) ;
393+
375394 public string GetGameExecutableName ( )
376395 {
377396 string [ ] exeNames = clientDefinitionsIni . GetStringListValue ( SETTINGS , "GameExecutableNames" , "Game.exe" ) ;
@@ -381,8 +400,15 @@ public string GetGameExecutableName()
381400
382401 public string GameLauncherExecutableName => clientDefinitionsIni . GetStringValue ( SETTINGS , "GameLauncherExecutableName" , string . Empty ) ;
383402
403+ public string [ ] GetCompatibilityCheckExecutables ( )
404+ {
405+ string [ ] exeNames = clientDefinitionsIni . GetStringListValue ( SETTINGS , "CompatibilityCheckExecutables" , string . Empty ) ;
406+
407+ return exeNames ;
408+ }
409+
384410 public bool SaveSkirmishGameOptions => clientDefinitionsIni . GetBooleanValue ( SETTINGS , "SaveSkirmishGameOptions" , false ) ;
385-
411+
386412 public bool SaveCampaignGameOptions => clientDefinitionsIni . GetBooleanValue ( SETTINGS , "SaveCampaignGameOptions" , false ) ;
387413
388414 public bool CreateSavedGamesDirectory => clientDefinitionsIni . GetBooleanValue ( SETTINGS , "CreateSavedGamesDirectory" , false ) ;
@@ -420,7 +446,7 @@ public string GetGameExecutableName()
420446 /// The main map file extension that is read by the client.
421447 /// </summary>
422448 public string MapFileExtension => clientDefinitionsIni . GetStringValue ( SETTINGS , "MapFileExtension" , "map" ) ;
423-
449+
424450 /// <summary>
425451 /// This tells the client which supplemental map files are ok to copy over during "spawnmap.ini" file creation.
426452 /// IE, if "BIN" is listed, then the client will look for and copy the file "map_a.bin"
@@ -505,6 +531,43 @@ public List<string> GetIRCServers()
505531
506532 public bool DiscordIntegrationGloballyDisabled => string . IsNullOrWhiteSpace ( DiscordAppId ) || DisableDiscordIntegration ;
507533
534+ public string CustomMissionPath => clientDefinitionsIni . GetStringValue ( SETTINGS , "CustomMissionPath" , "Maps/CustomMissions" ) ;
535+
536+ public List < ( string extension , string copyAs ) > GetCustomMissionSupplementFiles ( )
537+ {
538+ List < ( string extension , string copyAs ) > files = new ( ) ;
539+ Dictionary < string , int > extensionToIndex = new ( StringComparer . OrdinalIgnoreCase ) ;
540+
541+ int index = 0 ;
542+ while ( true )
543+ {
544+ string extensionKey = $ "CustomMissionSupplementFile{ index } Extension";
545+ string copyAsKey = $ "CustomMissionSupplementFile{ index } CopyAs";
546+
547+ string extension = clientDefinitionsIni . GetStringValue ( SETTINGS , extensionKey , null ) ? . Trim ( ) ;
548+
549+ // Stop iteration if the extension key is missing
550+ if ( string . IsNullOrWhiteSpace ( extension ) )
551+ break ;
552+
553+ string copyAs = clientDefinitionsIni . GetStringValue ( SETTINGS , copyAsKey , null ) ;
554+
555+ // Validate that copyAs is not empty
556+ if ( string . IsNullOrWhiteSpace ( copyAs ) )
557+ throw new ClientConfigurationException ( $ "Configuration key '{ copyAsKey } ' is required when '{ extensionKey } ' is present for supplement file { index } .") ;
558+
559+ // Validate that extension is unique
560+ if ( extensionToIndex . TryGetValue ( extension , out int firstIndex ) )
561+ throw new ClientConfigurationException ( $ "Duplicate extension '{ extension } ' found in supplement files. Extension is used in both file { firstIndex } and file { index } .") ;
562+
563+ extensionToIndex . Add ( extension , index ) ;
564+ files . Add ( ( extension , copyAs ) ) ;
565+ index ++ ;
566+ }
567+
568+ return files ;
569+ }
570+
508571 public OSVersion GetOperatingSystemVersion ( )
509572 {
510573#if NETFRAMEWORK
@@ -567,4 +630,4 @@ public ClientConfigurationException(string message) : base(message)
567630 {
568631 }
569632 }
570- }
633+ }
0 commit comments