Skip to content
Open
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
8beee92
Update UserINISettings.cs
CO2-code Feb 19, 2026
9c6b1c6
Remove RA specific settings from UserINISettings
CO2-code Feb 19, 2026
7bf4645
Update UserINISettings.cs
CO2-code Feb 22, 2026
1721273
Merge branch 'Ra1-Options' of https://github.com/CO2-code/xna-cncnet-…
CO2-code Feb 22, 2026
512d1e9
Update UserINISettings.cs
CO2-code Feb 22, 2026
542943c
Revert "Merge branch 'Ra1-Options' of https://github.com/CO2-code/xna…
CO2-code Feb 22, 2026
44f15db
Merge branch 'CnCNet:develop' into Ra1-Options
CO2-code Mar 4, 2026
66928c0
Update UserINISettings.cs
CO2-code Mar 5, 2026
7f0b5d9
Update UserINISettings.cs
CO2-code Mar 5, 2026
3ddd460
Update UserINISettings.cs
CO2-code Mar 5, 2026
0559426
Add new settings for detail level and input intervals
CO2-code Mar 5, 2026
625a1a7
Add KeyboardHotkeySection property to ClientConfiguration
CO2-code Mar 6, 2026
8992461
Refactor hotkey configuration handling
CO2-code Mar 6, 2026
5c2257a
Update ClientDefinitions.ini
CO2-code Mar 6, 2026
11c4f4a
Update UserINISettings.cs
CO2-code Mar 6, 2026
2820c26
Update UserINISettings.cs
CO2-code Mar 6, 2026
2e042c3
fixes :)
CO2-code Mar 6, 2026
a7fd805
Fix hotkey configuration file writing method
CO2-code Mar 6, 2026
624ed84
Add using directive for System namespace
CO2-code Mar 6, 2026
c80bb05
Update keyboardIni.Write to WriteIniFile with path
CO2-code Mar 6, 2026
2325dfd
Update HotkeyConfigurationWindow.cs
CO2-code Mar 6, 2026
46e4166
Remove 'WinHotkeys' section from settings
CO2-code Mar 6, 2026
5b39728
Remove hotkey section from settings if specified
CO2-code Mar 6, 2026
e8a8638
Refactor WriteKeyboardINI method for clarity
CO2-code Mar 6, 2026
d6f7774
Fix a typo
CO2-code Mar 7, 2026
dc99624
Remove hotkey section cleanup from settings
CO2-code Mar 7, 2026
9ea5c68
Save hotkey configuration when saving options
CO2-code Mar 7, 2026
a4666c6
Refactor HotkeyConfigurationWindow method call
CO2-code Mar 7, 2026
bca2b47
Remove hotkey configuration write during save
CO2-code Mar 7, 2026
67c7eae
Initialize UserINISettings for RA client type
CO2-code Mar 7, 2026
cc37971
Add WinHotkeys section conditionally in INI settings
CO2-code Mar 7, 2026
bf9e323
Refactor SaveSettings to use SettingsIni
CO2-code Mar 7, 2026
cf857e3
Enhance UserINISettings with hotkey section handling
CO2-code Mar 7, 2026
81b0031
Implement hotkey section management in settings
CO2-code Mar 7, 2026
25bf147
Update WriteKeyboardINI to use UserINISettings
CO2-code Mar 7, 2026
05bed27
Add ClientCore.Enums namespace to HotkeyConfigurationWindow
CO2-code Mar 7, 2026
74ec0db
simplify `MultiplayerScoreVolume` support
Metadorius Mar 7, 2026
f25247f
big cleanup and rewrite
Metadorius Mar 7, 2026
896774e
smol cleanup and no rewrite
Metadorius Mar 7, 2026
4291069
Apply suggestions from code review
Metadorius Mar 7, 2026
5072fcd
Remove unused ClientCore.Enums namespace
CO2-code Mar 8, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ClientCore/ClientConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,8 @@ private List<TranslationGameFile> ParseTranslationGameFiles()

public string KeyboardINI => clientDefinitionsIni.GetStringValue(SETTINGS, "KeyboardINI", "Keyboard.ini");

public string KeyboardHotkeySection => clientDefinitionsIni.GetStringValue(SETTINGS, "KeyboardHotkeySection", "Hotkey");

Comment on lines +368 to +371
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider that we already introduced so many hard coded ini key names for RA, when providing the default value of KeyboardHotkeySection, provide "WinHotKeys" as the default value when it's RA.

public int MinimumIngameWidth => clientDefinitionsIni.GetIntValue(SETTINGS, "MinimumIngameWidth", 640);

public int MinimumIngameHeight => clientDefinitionsIni.GetIntValue(SETTINGS, "MinimumIngameHeight", 480);
Expand Down
101 changes: 101 additions & 0 deletions ClientCore/Settings/UserINISettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,105 @@ protected UserINISettings(IniFile iniFile)
{
SettingsIni = iniFile;

if (ClientConfiguration.Instance.ClientGameType == ClientType.RA)
{
// ====================
// Display (Resolution)
// ====================
IngameScreenWidth = new IntSetting(iniFile, OPTIONS, "Width", 1024);
IngameScreenHeight = new IntSetting(iniFile, OPTIONS, "Height", 768);
ClientTheme = new StringSetting(iniFile, MULTIPLAYER, "Theme", ClientConfiguration.Instance.GetThemeInfoFromIndex(0).Name);
Translation = new StringSetting(iniFile, OPTIONS, "Translation", I18N.Translation.GetDefaultTranslationLocaleCode());
DetailLevel = new IntSetting(iniFile, OPTIONS, "DetailLevel", 2);
Renderer = new StringSetting(iniFile, COMPATIBILITY, "Renderer", string.Empty);
WindowedMode = new BoolSetting(iniFile, VIDEO, ClientConfiguration.Instance.WindowedModeKey, false);
BorderlessWindowedMode = new BoolSetting(iniFile, VIDEO, "NoWindowFrame", false);
BorderlessWindowedClient = new BoolSetting(iniFile, VIDEO, "BorderlessWindowedClient", ClientConfiguration.Instance.UserDefault_BorderlessWindowedClient);
IntegerScaledClient = new BoolSetting(iniFile, VIDEO, "IntegerScaledClient", ClientConfiguration.Instance.UserDefault_IntegerScaledClient);
ClientFPS = new IntSetting(iniFile, VIDEO, "ClientFPS", 60);
DisplayToggleableExtraTextures = new BoolSetting(iniFile, VIDEO, "DisplayToggleableExtraTextures", true);
Win8CompatMode = new StringSetting(iniFile, OPTIONS, "Win8Compat", "No");
// ====================
// GAME
// ====================
ScrollRate = new IntSetting(iniFile, OPTIONS, "ScrollRate", 3);

Difficulty = new IntSetting(iniFile, OPTIONS, "Difficulty", 1);
GameSpeed = new IntSetting(iniFile, OPTIONS, "GameSpeed", 1);
BackBufferInVRAM = new BoolSetting(iniFile, VIDEO, "VideoBackBuffer", false);
DragDistance = new IntSetting(iniFile, OPTIONS, "DragDistance", 4);
ForceLowestDetailLevel = new BoolSetting(iniFile, VIDEO, "ForceLowestDetailLevel", false);
DoubleTapInterval = new IntSetting(iniFile, OPTIONS, "DoubleTapInterval", 30);
ScrollDelay = new IntSetting(iniFile, OPTIONS, "ScrollDelay", 4);

// Remove binding completely
// DetailLevel = null;
// DragDistance = null;
// WindowedMode = null;
// BorderlessWindowedMode = null;
// BackBufferInVRAM = null;

// ====================
// AUDIO
// ====================
SoundVolume = new DoubleSetting(iniFile, OPTIONS, "Volume", 0.7);
ScoreVolume = new DoubleSetting(iniFile, OPTIONS, "ScoreVolume", 0.7);
MultiplayerScoreVolume = new DoubleSetting(iniFile, OPTIONS, "MultiplayerScoreVolume", 0.7);
VoiceVolume = new DoubleSetting(iniFile, AUDIO, "VoiceVolume", 0.7);
IsScoreShuffle = new BoolSetting(iniFile, AUDIO, "IsScoreShuffle", true);
ClientVolume = new DoubleSetting(iniFile, AUDIO, "ClientVolume", 1.0);
PlayMainMenuMusic = new BoolSetting(iniFile, AUDIO, "PlayMainMenuMusic", true);
StopMusicOnMenu = new BoolSetting(iniFile, AUDIO, "StopMusicOnMenu", true);
StopGameLobbyMessageAudio = new BoolSetting(iniFile, AUDIO, "StopGameLobbyMessageAudio", true);
MessageSound = new BoolSetting(iniFile, AUDIO, "ChatMessageSound", true);

// ====================
// Multiplayer
// ====================
PlayerName = new StringSetting(iniFile, MULTIPLAYER, "Handle", string.Empty);

ChatColor = new IntSetting(iniFile, MULTIPLAYER, "ChatColor", -1);
LANChatColor = new IntSetting(iniFile, MULTIPLAYER, "LANChatColor", -1);
PingUnofficialCnCNetTunnels = new BoolSetting(iniFile, MULTIPLAYER, "PingCustomTunnels", true);
WritePathToRegistry = new BoolSetting(iniFile, OPTIONS, "WriteInstallationPathToRegistry", ClientConfiguration.Instance.UserDefault_WriteInstallationPathToRegistry);
PlaySoundOnGameHosted = new BoolSetting(iniFile, MULTIPLAYER, "PlaySoundOnGameHosted", true);
SkipConnectDialog = new BoolSetting(iniFile, MULTIPLAYER, "SkipConnectDialog", false);
PersistentMode = new BoolSetting(iniFile, MULTIPLAYER, "PersistentMode", false);
AutomaticCnCNetLogin = new BoolSetting(iniFile, MULTIPLAYER, "AutomaticCnCNetLogin", false);
DiscordIntegration = new BoolSetting(iniFile, MULTIPLAYER, "DiscordIntegration", true);
SteamIntegration = new BoolSetting(iniFile, MULTIPLAYER, "SteamIntegration", true);
AllowGameInvitesFromFriendsOnly = new BoolSetting(iniFile, MULTIPLAYER, "AllowGameInvitesFromFriendsOnly", false);
NotifyOnUserListChange = new BoolSetting(iniFile, MULTIPLAYER, "NotifyOnUserListChange", true);
DisablePrivateMessagePopups = new BoolSetting(iniFile, MULTIPLAYER, "DisablePrivateMessagePopups", false);
AllowPrivateMessagesFromState = new IntSetting(iniFile, MULTIPLAYER, "AllowPrivateMessagesFromState", (int)AllowPrivateMessagesFromEnum.All);
EnableMapSharing = new BoolSetting(iniFile, MULTIPLAYER, "EnableMapSharing", true);
AlwaysDisplayTunnelList = new BoolSetting(iniFile, MULTIPLAYER, "AlwaysDisplayTunnelList", false);
MapSortState = new IntSetting(iniFile, MULTIPLAYER, "MapSortState", (int)SortDirection.None);
SearchAllGameModes = new BoolSetting(iniFile, MULTIPLAYER, "SearchAllGameModes", false);

CheckForUpdates = new BoolSetting(iniFile, OPTIONS, "CheckforUpdates", true);

PrivacyPolicyAccepted = new BoolSetting(iniFile, OPTIONS, "PrivacyPolicyAccepted", false);
IsFirstRun = new BoolSetting(iniFile, OPTIONS, "IsFirstRun", true);
CustomComponentsDenied = new BoolSetting(iniFile, OPTIONS, "CustomComponentsDenied", false);
//PreloadMapPreviews = new BoolSetting(iniFile, VIDEO, "PreloadMapPreviews", false);
MinimizeWindowsOnGameStart = new BoolSetting(iniFile, OPTIONS, "MinimizeWindowsOnGameStart", true);
AutoRemoveUnderscoresFromName = new BoolSetting(iniFile, OPTIONS, "AutoRemoveUnderscoresFromName", true);
GenerateTranslationStub = new BoolSetting(iniFile, OPTIONS, nameof(GenerateTranslationStub), false);
GenerateOnlyNewValuesInTranslationStub = new BoolSetting(iniFile, OPTIONS, nameof(GenerateOnlyNewValuesInTranslationStub), false);

SortState = new IntSetting(iniFile, GAME_FILTERS, "SortState", (int)SortDirection.None);
ShowFriendGamesOnly = new BoolSetting(iniFile, GAME_FILTERS, "ShowFriendGamesOnly", DEFAULT_SHOW_FRIENDS_ONLY_GAMES);
HideLockedGames = new BoolSetting(iniFile, GAME_FILTERS, "HideLockedGames", DEFAULT_HIDE_LOCKED_GAMES);
HidePasswordedGames = new BoolSetting(iniFile, GAME_FILTERS, "HidePasswordedGames", DEFAULT_HIDE_PASSWORDED_GAMES);
HideIncompatibleGames = new BoolSetting(iniFile, GAME_FILTERS, "HideIncompatibleGames", DEFAULT_HIDE_INCOMPATIBLE_GAMES);
MaxPlayerCount = new IntRangeSetting(iniFile, GAME_FILTERS, "MaxPlayerCount", DEFAULT_MAX_PLAYER_COUNT, 2, 8);

LoadFavoriteMaps(iniFile);
}
else
{

if (ClientConfiguration.Instance.ClientGameType == ClientType.TS)
BackBufferInVRAM = new BoolSetting(iniFile, VIDEO, "UseGraphicsPatch", true);
else
Expand Down Expand Up @@ -164,6 +263,7 @@ protected UserINISettings(IniFile iniFile)
MaxPlayerCount = new IntRangeSetting(iniFile, GAME_FILTERS, "MaxPlayerCount", DEFAULT_MAX_PLAYER_COUNT, 2, 8);

LoadFavoriteMaps(iniFile);
}
}

public IniFile SettingsIni { get; private set; }
Expand Down Expand Up @@ -200,6 +300,7 @@ protected UserINISettings(IniFile iniFile)
/* AUDIO */
/*********/

public DoubleSetting MultiplayerScoreVolume { get; private set; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure what is this for, some other score volume?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure what is this for, some other score volume?

yes ScoreVolume and MultiplayerScoreVolume are the game's "Music volume"
image

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be done in another way probably, not sure. @SadPencil @11EJDE11 opinions?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be done in another way probably, not sure. @SadPencil @11EJDE11 opinions?

can you re-review please

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure what is this for, some other score volume?

yes ScoreVolume and MultiplayerScoreVolume are the game's "Music volume" image

Can we assume ScoreVolume and MultiplayerScoreVolume always have the same values?

Copy link
Contributor Author

@CO2-code CO2-code Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure what is this for, some other score volume?

yes ScoreVolume and MultiplayerScoreVolume are the game's "Music volume" image

Can we assume ScoreVolume and MultiplayerScoreVolume always have the same values?

I am 100% sure that they should always have the same values , according to Iran's RAConfigTool ,

double MusicVolume = ((double)this.Slider_MusicVolume.Value) / 1000;
Files.RedAlertINI.setStringValue("Options", "ScoreVolume", MusicVolume.ToString());
Files.RedAlertINI.setStringValue("Options", "MultiplayerScoreVolume", MusicVolume.ToString());

public DoubleSetting ScoreVolume { get; private set; }
public DoubleSetting SoundVolume { get; private set; }
public DoubleSetting VoiceVolume { get; private set; }
Expand Down
12 changes: 7 additions & 5 deletions ClientGUI/HotkeyConfigurationWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ namespace ClientGUI
/// </summary>
public class HotkeyConfigurationWindow : XNAWindow
{
private readonly string HOTKEY_TIP_TEXT = "Press a key...".L10N("Client:DTAConfig:PressAKey");
private const string HOTKEY_INI_SECTION = "Hotkey";
private readonly string HOTKEY_TIP_TEXT = "Press a key...".L10N("Client:DTAConfig:PressAKey");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what changed in this specific line? did line ending change? that should be reverted as it litters the history with unnecessary changes

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I deleted (private const string HOTKEY_INI_SECTION = "Hotkey";) only

private const string KEYBOARD_COMMANDS_INI = "KeyboardCommands.ini";

public HotkeyConfigurationWindow(WindowManager windowManager) : base(windowManager)
Expand Down Expand Up @@ -298,7 +297,7 @@ private void LoadKeyboardINI()
{
foreach (var command in gameCommands)
{
int hotkey = keyboardINI.GetIntValue("Hotkey", command.ININame, 0);
int hotkey = keyboardINI.GetIntValue(ClientConfiguration.Instance.KeyboardHotkeySection, command.ININame, 0);

Hotkey hotkeyStruct = new Hotkey(hotkey);
command.Hotkey = new Hotkey(GetKeyOverride(hotkeyStruct.Key), hotkeyStruct.Modifier);
Expand Down Expand Up @@ -482,10 +481,13 @@ private KeyModifiers GetCurrentModifiers()

private void WriteKeyboardINI()
{
var keyboardIni = new IniFile();
var keyboardIni = new IniFile(SafePath.CombineFilePath(ProgramConstants.GamePath, ClientConfiguration.Instance.KeyboardINI));

keyboardIni.RemoveSection(ClientConfiguration.Instance.KeyboardHotkeySection);

foreach (var command in gameCommands)
{
keyboardIni.SetStringValue("Hotkey", command.ININame, command.Hotkey.GetTSEncoded().ToString());
keyboardIni.SetStringValue(ClientConfiguration.Instance.KeyboardHotkeySection, command.ININame, command.Hotkey.GetTSEncoded().ToString());
}

keyboardIni.WriteIniFile(SafePath.CombineFilePath(ProgramConstants.GamePath, ClientConfiguration.Instance.KeyboardINI));
Expand Down
3 changes: 3 additions & 0 deletions DXMainClient/Resources/ClientDefinitions.ini
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ RecommendedResolutions=1280x720 ;,1360x768,1366x768,2560x1440
; in the options menu
KeyboardINI=Keyboard.ini

; Hotkey section in KeyboardINI , for RA = WinHotkeys
KeyboardHotkeySection=Hotkey

; The name of the log file to parse statistics from at the end of the game
StatisticsLogFileName=TS.LOG

Expand Down
Loading