Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
94 commits
Select commit Hold shift + click to select a range
6f97167
Add migration tool project
MahBoiDeveloper Jul 3, 2025
d6c3c61
Test implementation
MahBoiDeveloper Jul 4, 2025
d9a7e58
Add more migration patches
MahBoiDeveloper Jul 4, 2025
40e6e28
Attempt to make VS2022 compile migration tool
MahBoiDeveloper Jul 4, 2025
d3e046c
Add latest client migration notes
MahBoiDeveloper Jul 5, 2025
028f8de
Add `MaximumRenderWidth` and `MaximumRenderHeight` keys into migration
MahBoiDeveloper Jul 5, 2025
6b0ee56
Refactor key writing and remove v2.12.5 version migration
MahBoiDeveloper Jul 5, 2025
18aca65
Add `PlayerExtraOptionsPanel.ini` migration
MahBoiDeveloper Jul 5, 2025
ae8ed16
Fix typo
MahBoiDeveloper Jul 5, 2025
b7ddb2f
Move changes for v2.12.0 to patch for 2.11.0
MahBoiDeveloper Jul 5, 2025
96d9225
Refactoring and rewording
MahBoiDeveloper Jul 5, 2025
0122a2f
Rework v2.11.1 patch
MahBoiDeveloper Jul 5, 2025
5e2661d
Switch expression optimization and add `GenericWindow.ini` migration
MahBoiDeveloper Jul 5, 2025
8104dde
Add patch rename `CustomSettingFile*` to `FileSetting*`
MahBoiDeveloper Jul 6, 2025
b7a3c48
Fix bug with potential null reference exception when section does not…
MahBoiDeveloper Jul 6, 2025
540ea08
Adjustments (new keys for `OptionsWindow.ini`, bug fix, improvemetns)
MahBoiDeveloper Jul 6, 2025
e3f72ba
Rework exception catch
MahBoiDeveloper Jul 6, 2025
6e2535f
Rework patch apply mechanism
MahBoiDeveloper Jul 6, 2025
6281d7d
Adjustments in enums
MahBoiDeveloper Jul 6, 2025
e7d8a1f
Rework logging
MahBoiDeveloper Jul 6, 2025
6edabf1
Refactoring patch v2.11.0
MahBoiDeveloper Jul 6, 2025
82a7765
Start migration configs from 2.8.x.x
MahBoiDeveloper Jul 6, 2025
60fccd0
Add experimental config transfer from `GameOptions.ini` to `GameLobby…
MahBoiDeveloper Jul 6, 2025
40e92db
Transfering keys optimization
MahBoiDeveloper Jul 7, 2025
9ee8b29
Refactoring ini-files naming
MahBoiDeveloper Jul 7, 2025
0122f8a
Optimizations
MahBoiDeveloper Jul 7, 2025
a66d251
Add more config transfer for `MultiplayerGameLobby.ini`
MahBoiDeveloper Jul 7, 2025
c06116a
Fix inheritance
MahBoiDeveloper Jul 7, 2025
88c15e5
Refactoring and finilizing `GameLobbyBase.ini` creation
MahBoiDeveloper Jul 7, 2025
ecea407
Refactoring
MahBoiDeveloper Jul 7, 2025
27b3c13
Migrate other controls for `MultiplayerGameLobby.ini`
MahBoiDeveloper Jul 8, 2025
31425ef
Fix mistake for writing client parser constants
MahBoiDeveloper Jul 8, 2025
6509dbf
Fix potential client crash if `lbChatMessages` and `tbChatInput` and …
MahBoiDeveloper Jul 8, 2025
0466e03
Improve game guessing
MahBoiDeveloper Jul 8, 2025
937747d
Add status images
MahBoiDeveloper Jul 8, 2025
9951138
Compile and copy absent images
MahBoiDeveloper Jul 8, 2025
fbb3089
Update mistake in docs
MahBoiDeveloper Jul 8, 2025
38e42dd
Add more images
MahBoiDeveloper Jul 8, 2025
1b5b0fd
Fix possible bugs with transefing section keys and OptionsWindow new …
MahBoiDeveloper Jul 8, 2025
c741550
Add `GameOptionsPanel` child controls position recalculation
MahBoiDeveloper Jul 8, 2025
ac8e5c3
Show detailed error message
SadPencil Jul 8, 2025
bdbe183
Fix null reference on catching the first failed patch
SadPencil Jul 8, 2025
ed521dc
Remove images
MahBoiDeveloper Jul 8, 2025
fe4b62e
Add force enabling borders to draw
MahBoiDeveloper Jul 8, 2025
7bf1626
Add patch for client version v2.12.6
MahBoiDeveloper Jul 11, 2025
30929bb
Replace cast to hash set with `Distinct()` method
MahBoiDeveloper Jul 12, 2025
6cf7ae0
Apply 2.12.6 release migration notes
MahBoiDeveloper Jul 13, 2025
ce74dc5
Add patch for renamed in PR#534 btnSaveLoadGameOptions
MahBoiDeveloper Jul 14, 2025
a6da43d
Enable nullable globally for MigrationTool
SadPencil Jul 16, 2025
317bf78
Address the nullable issue in Program.cs
SadPencil Jul 16, 2025
9ee0f06
Merge branch 'feature/migration-tool' of https://github.com/MahBoiDev…
SadPencil Jul 16, 2025
4fceaff
Merge branch 'develop' into pr/774
SadPencil Jul 16, 2025
cd3fa39
Fix handling SkirmishLobby in gameOptionsIni
SadPencil Jul 16, 2025
95c75c8
GenericWindow.ini: DrawBorders = false
SadPencil Jul 16, 2025
434a218
Use new C# syntax to determine the `arg`
SadPencil Jul 16, 2025
5b26734
Format codes in Visual Studio
SadPencil Jul 16, 2025
92f2fb6
Rename `exefile` to `resourceName`
SadPencil Jul 16, 2025
9e95a3e
Use FileMode.CreateNew since the file does not exist
SadPencil Jul 16, 2025
79ddb63
Move optionsWindowIni to a nested block
SadPencil Jul 16, 2025
de40f80
Change return type of `Apply()` to void
SadPencil Jul 16, 2025
5a2bf9e
Merge branch 'develop' into pr/774
SadPencil Jul 16, 2025
674811d
Rework patch apply mechanism to use reflection
MahBoiDeveloper Jul 16, 2025
2c8d8ad
Merge branch 'feature/migration-tool' of https://github.com/MahBoiDev…
SadPencil Jul 16, 2025
a4256e3
Upate patch apply mechanism
MahBoiDeveloper Jul 16, 2025
5f135f4
Refactoring
MahBoiDeveloper Jul 16, 2025
53cc0f3
Remove debug lines
MahBoiDeveloper Jul 16, 2025
667622e
Fix compilation error
MahBoiDeveloper Jul 16, 2025
128a8bf
Rework patch class daughter search
MahBoiDeveloper Jul 16, 2025
37b84aa
Merge CnCNet/develop
MahBoiDeveloper Aug 11, 2025
3218472
Merge develop → feature
MahBoiDeveloper Sep 26, 2025
1680291
Fix building
MahBoiDeveloper Sep 26, 2025
fd40066
Rework Directory* xml files
MahBoiDeveloper Sep 27, 2025
8455a80
Make compiler happy
MahBoiDeveloper Sep 30, 2025
20bafff
Add info about migration tool to the docs
MahBoiDeveloper Oct 1, 2025
d80163e
Rewording log message
MahBoiDeveloper Oct 22, 2025
d54ccda
Add `RemoveKeyWithLog`
MahBoiDeveloper Oct 22, 2025
31844b4
Add log message about renaming custom checkboxes and dropdowns in `Op…
MahBoiDeveloper Oct 22, 2025
98ad9eb
Add backup notice in documentation
MahBoiDeveloper Oct 22, 2025
fbbbdfc
Merge develop → feature
MahBoiDeveloper Oct 23, 2025
d064b22
Merge develop → feature
MahBoiDeveloper Nov 26, 2025
467d078
Add migration tool to the project list in slnx file
MahBoiDeveloper Nov 26, 2025
2e5f43b
Add .NET 4.8 build
MahBoiDeveloper Dec 1, 2025
fdedaa7
Merge develop → feature
MahBoiDeveloper Dec 13, 2025
e6e0159
Merge develop → feature
MahBoiDeveloper Dec 19, 2025
ab0f4d4
Update submodule
MahBoiDeveloper Jan 12, 2026
a25ece9
Merge develop → feature
MahBoiDeveloper Jan 12, 2026
ae866c9
Merge develop → feature
MahBoiDeveloper Jan 26, 2026
3bdc03b
Fix warning
MahBoiDeveloper Jan 26, 2026
c7393ce
Refactoring names for const vars
MahBoiDeveloper Jan 26, 2026
133e08c
Add more spacing
MahBoiDeveloper Jan 26, 2026
7fc5508
Fix warnings
MahBoiDeveloper Jan 26, 2026
9628e8b
Merge develop → feature
MahBoiDeveloper Jan 27, 2026
f02cd77
Refactore removing Rampastring.Tools.* near to the client*.exe
MahBoiDeveloper Feb 6, 2026
963ceb9
Rework patching game lobbies
MahBoiDeveloper Feb 6, 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
1 change: 1 addition & 0 deletions DXClient.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
<BuildType Solution="WindowsXNADebug|*" Project="Debug" />
<BuildType Solution="WindowsXNARelease|*" Project="Release" />
</Project>
<Project Path="MigrationTool/MigrationTool.csproj" />
<Project Path="Rampastring.XNAUI/Rampastring.XNAUI.csproj" />
<Project Path="SecondStageUpdater/SecondStageUpdater.csproj" />
<Project Path="TranslationNotifierGenerator/TranslationNotifierGenerator.csproj" />
Expand Down
8 changes: 8 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,14 @@
<Platforms>AnyCPU</Platforms>
</PropertyGroup>

<PropertyGroup Condition="'$(MSBuildProjectName)' == 'MigrationTool'">
<TargetFrameworks>net8.0;net48</TargetFrameworks>
<RuntimeIdentifiers Condition="'$(TargetFramework)' == 'net48'">win-x86</RuntimeIdentifiers>
<Platforms>AnyCPU</Platforms>
<Nullable>enable</Nullable>
<OutputType>Exe</OutputType>
</PropertyGroup>

<!-- For Constants -->
<PropertyGroup>
<!-- Is Debug -->
Expand Down
29 changes: 29 additions & 0 deletions Directory.Build.targets
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,19 @@
Projects="$(MSBuildThisFileDirectory)SecondStageUpdater\SecondStageUpdater.csproj"
Properties="TargetFramework=$(TargetFramework.Split('-')[0]);Platform=AnyCPU;RuntimeIdentifier=" />
</Target>

<Target Name="RestoreMigrationTool" AfterTargets="Restore" Condition="'$(PublishDir)' != '' AND '$(MSBuildProjectName)' == 'MigrationTool'">
<MSBuild
Projects="$(MSBuildThisFileDirectory)MigrationTool\MigrationTool.csproj"
Properties="TargetFramework=$(TargetFramework);Platform=$(Platform);RuntimeIdentifier="
Targets="Restore" />
</Target>

<Target Name="BuildMigrationTool" AfterTargets="Build" Condition="'$(PublishDir)' != '' AND '$(MSBuildProjectName)' == 'MigrationTool'">
<MSBuild
Projects="$(MSBuildThisFileDirectory)MigrationTool\MigrationTool.csproj"
Properties="TargetFramework=$(TargetFramework);Platform=$(Platform);RuntimeIdentifier=" />
</Target>

<Target Name="MakeDirectoryStructure" AfterTargets="Publish" Condition="'$(MSBuildProjectName)' == 'DXMainClient'">
<CallTarget Targets="PublishNetFrameworkWindowsGLNative;RemoveNetFrameworkWindowsGLNative;RemoveWindowsDXNonWindowsBinaries;RemoveWindowsGLNonWindowsBinaries;RemoveGLMobileBinaries" />
Expand Down Expand Up @@ -138,6 +151,22 @@
<Delete Files="%(CNCNetUpdaterOutputFile.Identity)" Condition="Exists('$(CNCNetUpdaterCopyTo)%(CNCNetUpdaterOutputFile.Identity)')" />
</Target>

<Target Name="CopyMigrationTool" AfterTargets="Build" Condition="'$(PublishDir)' != '' AND '$(MSBuildProjectName)' == 'MigrationTool'">
<PropertyGroup>
<CNCNetMigrationToolCopyTo>$(PublishDir)\..\MigrationTool\</CNCNetMigrationToolCopyTo>
</PropertyGroup>
<ItemGroup>
<CNCNetMigrationToolOutputFile Include="$(OutputPath)\*.*" />
</ItemGroup>
<Copy SourceFiles="@(CNCNetMigrationToolOutputFile)" DestinationFolder="$(CNCNetMigrationToolCopyTo)" />
</Target>

<Target Name="MoveMigrationTool" Condition="'$(MSBuildProjectName)' == 'MigrationTool'">
<Message Importance="high" Text="Moving migration tool executables" />
<Move SourceFiles="%(CNCNetMigrationToolOutputFile.Identity)" DestinationFolder="$(CNCNetMigrationToolCopyTo)" Condition="!Exists('$(CNCNetMigrationToolCopyTo)%(CNCNetMigrationToolOutputFile.Identity)')" />
<Delete Files="%(CNCNetMigrationToolOutputFile.Identity)" Condition="Exists('$(CNCNetMigrationToolCopyTo)%(CNCNetMigrationToolOutputFile.Identity)')" />
</Target>

<!-- Allow a game specific build prop file to be imported, if available -->
<Import Project="$(MSBuildThisFileDirectory)Directory.targets" Condition="Exists('$(MSBuildThisFileDirectory)Directory.targets')" />

Expand Down
9 changes: 6 additions & 3 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,14 @@
<PackageVersion Include="System.Text.Json" Version="8.0.6" />
<PackageVersion Include="Ude.NetStandard" Version="1.2.0" />
</ItemGroup>
<ItemGroup Condition="'$(MSBuildProjectName)' == 'ClientCore' Or '$(MSBuildProjectName)' == 'ClientGUI' Or '$(MSBuildProjectName)' == 'DTAConfig' Or '$(MSBuildProjectName)' == 'DXMainClient' Or '$(MSBuildProjectName)' == 'ClientUpdater'">
<ItemGroup Condition="'$(MSBuildProjectName)' == 'ClientCore'
Or '$(MSBuildProjectName)' == 'ClientGUI'
Or '$(MSBuildProjectName)' == 'ClientUpdater'
Or '$(MSBuildProjectName)' == 'DXMainClient'">
<ProjectReference Include="$(MSBuildThisFileDirectory)TranslationNotifierGenerator\TranslationNotifierGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
</ItemGroup>
<!-- Polyfill on .NET 4.8 (SecondStageUpdater excluded) -->
<ItemGroup Condition="'$(MSBuildProjectName)' != 'SecondStageUpdater' And $(TargetFrameworkIdentifier) == '.NETFramework'">
<!-- Polyfill on .NET 4.8 (SecondStageUpdater and MigrationTool excluded) -->
<ItemGroup Condition="'$(MSBuildProjectName)' != 'SecondStageUpdater' and '$(MSBuildProjectName)' != 'MigrationTool' and $(TargetFrameworkIdentifier) == '.NETFramework'">
<GlobalPackageReference Include="Polyfill" Version="6.14.0" />
<PackageReference Include="System.ValueTuple" Condition="$(TargetFramework.StartsWith('net46'))" />
<PackageVersion Include="System.ValueTuple" Version="4.5.0" />
Expand Down
4 changes: 3 additions & 1 deletion Docs/Migration-INI.md
Original file line number Diff line number Diff line change
Expand Up @@ -724,7 +724,7 @@ DrawBorders=true
Size=1230,750
```

## Edit `GlobalThemeSettings.ini`
## Edit `DTACnCNetClient.ini`

This file now also contains the `ParserConstants` section, which lists user-defined constants used for positioning controls within panels and windows. **Without this section, the client will crash with new `GameLobbyBase.ini` layout**.

Expand Down Expand Up @@ -806,6 +806,8 @@ Location=470,137
Location=0,200

[btnForceUpdate]
Location=407,213
Size=133,23
```

2. **OPTIONAL** Add sections:
Expand Down
8 changes: 8 additions & 0 deletions Docs/Migration.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
Migrating from older versions
-----------------------------

> [!NOTE]
> CnCNet has a program called `Migration Tool` that implements all the instructions described down below notices to automate the migration process.
> To use this tool, download the latest nightly build and run `Resources\BinariesNET8\MigrationTool\MigrationTool.exe` with older client path as the first argument.
>
> Example: `MigrationTool.exe C:\TiberianSunClient`
>
> It is recommended that you back up the client configuration before running the migration tool.

This document lists all the breaking changes and how to address them. Each section corresponds to the migration steps that are required to upgrade to the selected version. If you're skipping multiple versions in the upgrade process - you have to apply all corresponding migration steps.

> [!NOTE]
Expand Down
29 changes: 29 additions & 0 deletions MigrationTool/MigrationTool.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Title>CnCNet.MigrationTool</Title>
<Description>CnCNet Client Migration Tool</Description>
<Product>CnCNet.MigrationTool</Product>
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="Pictures\favActive.png" />
<EmbeddedResource Include="Pictures\favActive_c.png" />
<EmbeddedResource Include="Pictures\favInactive.png" />
<EmbeddedResource Include="Pictures\noMapPreview.png" />
<EmbeddedResource Include="Pictures\sortAlphaActive.png" />
<EmbeddedResource Include="Pictures\sortAlphaAsc.png" />
<EmbeddedResource Include="Pictures\sortAlphaDesc.png" />
<EmbeddedResource Include="Pictures\sortAlphaInactive.png" />
<EmbeddedResource Include="Pictures\sortAlphaNone.png" />
<EmbeddedResource Include="Pictures\statusAI.png" />
<EmbeddedResource Include="Pictures\statusClear.png" />
<EmbeddedResource Include="Pictures\statusEmpty.png" />
<EmbeddedResource Include="Pictures\statusError.png" />
<EmbeddedResource Include="Pictures\statusInProgress.png" />
<EmbeddedResource Include="Pictures\statusOk.png" />
<EmbeddedResource Include="Pictures\statusUnavailable.png" />
<EmbeddedResource Include="Pictures\statusWarning.png" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ClientCore\ClientCore.csproj" />
</ItemGroup>
</Project>
156 changes: 156 additions & 0 deletions MigrationTool/Patch.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
using System.IO;
using System.Linq;
using System.Collections.Generic;

using Rampastring.Tools;
using ClientCore.Enums;
namespace MigrationTool;

internal abstract class Patch
{
public Version ClientVersion { get; protected set; }
public ClientType Game { get; protected set; }
public DirectoryInfo ClientDir { get; protected set; }
public DirectoryInfo ResouresDir { get; protected set; }

public Patch(string clientPath)
{
ClientDir = SafePath.GetDirectory(clientPath);
ResouresDir = SafePath.GetDirectory(SafePath.CombineFilePath(clientPath, "Resources"));

// Predict client type by guessing game engine files
Game = ClientType.TS;

if (SafePath.GetFile(SafePath.CombineFilePath(ClientDir.FullName, "Ares.dll")).Exists)
{
Game = ClientType.Ares;
}
else if (SafePath.GetFile(SafePath.CombineFilePath(ClientDir.FullName, "gamemd-spawn.dll")).Exists)
{
Game = ClientType.YR;
}
}

public virtual void Apply()
{
Logger.Log($"Applying patch for client version {ClientVersion.ToString().Replace('_', '.')}...");
}

public Patch AddKeyWithLog(IniFile src, string section, string key, string value)
{
if (src.KeyExists(section, key))
{
Logger.Log($"Update {src.FileName}: Skip adding [{section}]->{key}, reason: already exist");
}
else
{
Logger.Log($"Update {src.FileName}: Add [{section}]->{key}={value}");

if (!src.SectionExists(section))
src.AddSection(section);

src.GetSection(section).AddKey(key, value);
}

return this;
}

public Patch RemoveKeyWithLog(IniFile src, string section, string key)
{
if (!src.KeyExists(section, key))
{
Logger.Log($"Update {src.FileName}: Skip removing [{section}]->{key}, reason: doesn't exist");
}
else
{
Logger.Log($"Update {src.FileName}: Remove [{section}]->{key}={src.GetSection(section).Keys.First(kvp => kvp.Key == key).Value}");
src.GetSection(section).RemoveKey(key);
}

return this;
}

public void CalculatePositions(IniFile ini, string parent, string child)
{
int parentX, parentY, childX, childY;
parentX = parentY = childX = childY = 0;

var parentKeys = ini.GetSectionKeys(parent);
var childKeys = ini.GetSectionKeys(child);

var positionKeys = new List<string>() { "$X", "$Y", "X", "Y", "Location" };

Logger.Log($"Update {ini.FileName}: Fix position for {child} control in {parent}");

foreach (var control in new List<List<string>>() { parentKeys, childKeys })
{
int tmpX, tmpY;
tmpX = tmpY = 0;

foreach (var key in control.Where(key => positionKeys.Contains(key)))
{
switch (key)
{
case ("$X"):
case ("X"):
tmpX = ini.GetIntValue(control == parentKeys ? parent : child, key, tmpX);
continue;
case ("$Y"):
case ("Y"):
tmpY = ini.GetIntValue(control == parentKeys ? parent : child, key, tmpY);
continue;
case ("Location"):
var value = ini.GetStringValue(control == parentKeys ? parent : child, key, string.Empty).Split(',');
tmpX = Conversions.IntFromString(value[0], tmpX);
tmpY = Conversions.IntFromString(value[1], tmpY);
break;
default:
break;
}
}

if (control == parentKeys)
{
parentX = tmpX;
parentY = tmpY;
}
else
{
childX = tmpX;
childY = tmpY;
}
}

positionKeys.ForEach(key => ini.RemoveKey(child, key));

childX = childX - parentX;
childY = childY - parentY;

ini.GetSection(child).AddKey("$X", $"{childX}");
ini.GetSection(child).AddKey("$Y", $"{childY}");
}

public Patch TransferKeys(IniFile srcIni, string srcSection, IniFile desIni, string? desSection = null)
{
desSection ??= srcSection;

srcIni.GetSectionKeys(srcSection)
.ForEach(key => AddKeyWithLog(desIni, desSection, key, srcIni.GetStringValue(srcSection, key, string.Empty)));

return this;
}

public bool TryApply()
{
try
{
Apply();
return true;
}
catch
{
return false;
}
}
}

21 changes: 21 additions & 0 deletions MigrationTool/Patch_Latest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System.Linq;

using Rampastring.Tools;

namespace MigrationTool;

internal class Patch_Latest : Patch
{
public Patch_Latest(string clientPath) : base(clientPath)
{
ClientVersion = Version.Latest;
}

public override void Apply()
{
base.Apply();

// Write latest patch there
}
}

Loading
Loading