Skip to content

Commit 95d43c2

Browse files
authored
Merge pull request #616 from CnCNet/develop
2.11.6.0
2 parents f6b6b48 + ff5f14c commit 95d43c2

22 files changed

+282
-64
lines changed

ClientCore/ClientConfiguration.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,8 @@ private List<TranslationGameFile> ParseTranslationGameFiles()
330330

331331
public string AllowedCustomGameModes => clientDefinitionsIni.GetStringValue(SETTINGS, "AllowedCustomGameModes", "Standard,Custom Map");
332332

333+
public string SkillLevelOptions => clientDefinitionsIni.GetStringValue(SETTINGS, "SkillLevelOptions", "Any,Beginner,Intermediate,Pro");
334+
333335
public string GetGameExecutableName()
334336
{
335337
string[] exeNames = clientDefinitionsIni.GetStringValue(SETTINGS, "GameExecutableNames", "Game.exe").Split(',');
@@ -422,6 +424,25 @@ public IEnumerable<string> SupplementalMapFileExtensions
422424

423425
#endregion
424426

427+
#region Game networking defaults
428+
429+
/// <summary>
430+
/// Default value for FrameSendRate setting written in spawn.ini.
431+
/// </summary>
432+
public int DefaultFrameSendRate => clientDefinitionsIni.GetIntValue(SETTINGS, nameof(DefaultFrameSendRate), 7);
433+
434+
/// <summary>
435+
/// Default value for Protocol setting written in spawn.ini.
436+
/// </summary>
437+
public int DefaultProtocolVersion => clientDefinitionsIni.GetIntValue(SETTINGS, nameof(DefaultProtocolVersion), 2);
438+
439+
/// <summary>
440+
/// Default value for MaxAhead setting written in spawn.ini.
441+
/// </summary>
442+
public int DefaultMaxAhead => clientDefinitionsIni.GetIntValue(SETTINGS, nameof(DefaultMaxAhead), 0);
443+
444+
#endregion
445+
425446
public List<string> GetIRCServers()
426447
{
427448
List<string> servers = [];

ClientCore/CnCNet5/GameCollection.cs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public void Initialize()
6666
GameBroadcastChannel = "#cncnet-dta-games",
6767
InternalName = "dta",
6868
RegistryInstallPath = "HKCU\\Software\\TheDawnOfTheTiberiumAge",
69-
UIName = "Dawn of the Tiberium Age".L10N("Client:Core:DawnoftheTiberiumAge"),
69+
UIName = "Dawn of the Tiberium Age".L10N("Client:ClientCore:DawnoftheTiberiumAge"),
7070
Texture = AssetLoader.TextureFromImage(dtaIcon)
7171
},
7272

@@ -77,7 +77,7 @@ public void Initialize()
7777
GameBroadcastChannel = "#cncnet-ti-games",
7878
InternalName = "ti",
7979
RegistryInstallPath = "HKCU\\Software\\TwistedInsurrection",
80-
UIName = "Twisted Insurrection".L10N("Client:Core:TwistedInsurrection"),
80+
UIName = "Twisted Insurrection".L10N("Client:ClientCore:TwistedInsurrection"),
8181
Texture = AssetLoader.TextureFromImage(tiIcon)
8282
},
8383

@@ -88,7 +88,7 @@ public void Initialize()
8888
GameBroadcastChannel = "#cncnet-mo-games",
8989
InternalName = "mo",
9090
RegistryInstallPath = "HKCU\\Software\\MentalOmega",
91-
UIName = "Mental Omega".L10N("Client:Core:MentalOmega"),
91+
UIName = "Mental Omega".L10N("Client:ClientCore:MentalOmega"),
9292
Texture = AssetLoader.TextureFromImage(moIcon)
9393
},
9494

@@ -99,7 +99,7 @@ public void Initialize()
9999
GameBroadcastChannel = "#redres-games",
100100
InternalName = "rr",
101101
RegistryInstallPath = "HKLM\\Software\\RedResurrection",
102-
UIName = "YR Red-Resurrection".L10N("Client:Core:YRRedResurrection"),
102+
UIName = "YR Red-Resurrection".L10N("Client:ClientCore:YRRedResurrection"),
103103
Texture = AssetLoader.TextureFromImage(rrIcon)
104104
},
105105

@@ -110,7 +110,7 @@ public void Initialize()
110110
GameBroadcastChannel = "#rote-games",
111111
InternalName = "re",
112112
RegistryInstallPath = "HKLM\\Software\\RiseoftheEast",
113-
UIName = "Rise of the East".L10N("Client:Core:RiseoftheEast"),
113+
UIName = "Rise of the East".L10N("Client:ClientCore:RiseoftheEast"),
114114
Texture = AssetLoader.TextureFromImage(reIcon)
115115
},
116116

@@ -121,7 +121,7 @@ public void Initialize()
121121
GameBroadcastChannel = "#cncreloaded-games",
122122
InternalName = "cncr",
123123
RegistryInstallPath = "HKCU\\Software\\CnCReloaded",
124-
UIName = "C&C: Reloaded".L10N("Client:Core:CnCReloaded"),
124+
UIName = "C&C: Reloaded".L10N("Client:ClientCore:CnCReloaded"),
125125
Texture = AssetLoader.TextureFromImage(cncrIcon)
126126
},
127127

@@ -132,7 +132,7 @@ public void Initialize()
132132
GameBroadcastChannel = "#cncnet-td-games",
133133
InternalName = "td",
134134
RegistryInstallPath = "HKLM\\Software\\Westwood\\Tiberian Dawn",
135-
UIName = "Tiberian Dawn".L10N("Client:Core:TiberianDawn"),
135+
UIName = "Tiberian Dawn".L10N("Client:ClientCore:TiberianDawn"),
136136
Texture = AssetLoader.TextureFromImage(tdIcon),
137137
Supported = false
138138
},
@@ -144,7 +144,7 @@ public void Initialize()
144144
GameBroadcastChannel = "#cncnet-ra-games",
145145
InternalName = "ra",
146146
RegistryInstallPath = "HKLM\\Software\\Westwood\\Red Alert",
147-
UIName = "Red Alert".L10N("Client:Core:RedAlert"),
147+
UIName = "Red Alert".L10N("Client:ClientCore:RedAlert"),
148148
Texture = AssetLoader.TextureFromImage(raIcon),
149149
Supported = false
150150
},
@@ -156,7 +156,7 @@ public void Initialize()
156156
GameBroadcastChannel = "#cncnet-d2k-games",
157157
InternalName = "d2k",
158158
RegistryInstallPath = "HKLM\\Software\\Westwood\\Dune 2000",
159-
UIName = "Dune 2000".L10N("Client:Core:Dune2000"),
159+
UIName = "Dune 2000".L10N("Client:ClientCore:Dune2000"),
160160
Texture = AssetLoader.TextureFromImage(d2kIcon),
161161
Supported = false
162162
},
@@ -168,7 +168,7 @@ public void Initialize()
168168
GameBroadcastChannel = "#cncnet-ts-games",
169169
InternalName = "ts",
170170
RegistryInstallPath = "HKLM\\Software\\Westwood\\Tiberian Sun",
171-
UIName = "Tiberian Sun".L10N("Client:Core:TiberianSun"),
171+
UIName = "Tiberian Sun".L10N("Client:ClientCore:TiberianSun"),
172172
Texture = AssetLoader.TextureFromImage(tsIcon)
173173
},
174174

@@ -179,7 +179,7 @@ public void Initialize()
179179
GameBroadcastChannel = "#cncnet-yr-games",
180180
InternalName = "yr",
181181
RegistryInstallPath = "HKLM\\Software\\Westwood\\Yuri's Revenge",
182-
UIName = "Yuri's Revenge".L10N("Client:Core:YurisRevenge"),
182+
UIName = "Yuri's Revenge".L10N("Client:ClientCore:YurisRevenge"),
183183
Texture = AssetLoader.TextureFromImage(yrIcon)
184184
},
185185

@@ -190,7 +190,7 @@ public void Initialize()
190190
GameBroadcastChannel = "#cncnet-ss-games",
191191
InternalName = "ss",
192192
RegistryInstallPath = "HKLM\\Software\\Westwood\\Sole Survivor",
193-
UIName = "Sole Survivor".L10N("Client:Core:SoleSurvivor"),
193+
UIName = "Sole Survivor".L10N("Client:ClientCore:SoleSurvivor"),
194194
Texture = AssetLoader.TextureFromImage(ssIcon),
195195
Supported = false
196196
}
@@ -203,7 +203,7 @@ public void Initialize()
203203
{
204204
ChatChannel = "#cncnet",
205205
InternalName = "cncnet",
206-
UIName = "General CnCNet Chat".L10N("Client:Core:GeneralCnCNetChat"),
206+
UIName = "General CnCNet Chat".L10N("Client:ClientCore:GeneralCnCNetChat"),
207207
AlwaysEnabled = true,
208208
Texture = AssetLoader.TextureFromImage(cncnetIcon)
209209
}

ClientCore/ProgramConstants.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public static class ProgramConstants
2626

2727
public const string QRES_EXECUTABLE = "qres.dat";
2828

29-
public const string CNCNET_PROTOCOL_REVISION = "R11";
29+
public const string CNCNET_PROTOCOL_REVISION = "R12";
3030
public const string LAN_PROTOCOL_REVISION = "RL7";
3131
public const int LAN_PORT = 1234;
3232
public const int LAN_INGAME_PORT = 1234;

ClientUpdater/CustomComponent.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ namespace ClientUpdater;
2323
using System.Net.Http.Handlers;
2424
using System.Threading;
2525
using System.Threading.Tasks;
26+
2627
using ClientUpdater.Compression;
28+
2729
using Rampastring.Tools;
2830

2931
/// <summary>
@@ -377,7 +379,10 @@ private void CleanUpAfterDownload()
377379
foreach (string filename in filesToCleanup)
378380
{
379381
if (File.Exists(filename))
382+
{
383+
new FileInfo(filename).IsReadOnly = false;
380384
File.Delete(filename);
385+
}
381386
}
382387
}
383388
catch (Exception)

ClientUpdater/Updater.cs

Lines changed: 67 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ namespace ClientUpdater;
3030
using System.Text;
3131
using System.Threading;
3232
using System.Threading.Tasks;
33+
3334
using ClientUpdater.Compression;
35+
3436
using Rampastring.Tools;
3537

3638
public static class Updater
@@ -429,6 +431,8 @@ internal static void DeleteFileAndWait(string filepath, int timeout = 10000)
429431
{
430432
mre.Set();
431433
};
434+
if (fileInfo.Exists)
435+
fileInfo.IsReadOnly = false;
432436
fileInfo.Delete();
433437
mre.Wait(timeout);
434438
}
@@ -613,15 +617,15 @@ private static async Task DoVersionCheckAsync()
613617

614618
UpdateUserAgent(SharedHttpClient);
615619

616-
FileInfo downloadFile = SafePath.GetFile(GamePath, FormattableString.Invariant($"{VERSION_FILE}_u"));
620+
FileInfo versionFile = SafePath.GetFile(GamePath, FormattableString.Invariant($"{VERSION_FILE}_u"));
617621

618622
while (currentUpdateMirrorIndex < updateMirrors.Count)
619623
{
620624
try
621625
{
622626
Logger.Log("Updater: Trying to connect to update mirror " + updateMirrors[currentUpdateMirrorIndex].URL);
623627

624-
FileStream fileStream = new FileStream(downloadFile.FullName, FileMode.Create, FileAccess.Write, FileShare.None, 4096, FileOptions.Asynchronous);
628+
FileStream fileStream = new FileStream(versionFile.FullName, FileMode.Create, FileAccess.Write, FileShare.None, 4096, FileOptions.Asynchronous);
625629

626630
using (fileStream)
627631
{
@@ -650,7 +654,7 @@ private static async Task DoVersionCheckAsync()
650654
}
651655

652656
Logger.Log("Updater: Downloaded version information.");
653-
var version = new IniFile(downloadFile.FullName);
657+
var version = new IniFile(versionFile.FullName);
654658
string versionString = version.GetStringValue("DTA", "Version", string.Empty);
655659
string updaterVersionString = version.GetStringValue("DTA", "UpdaterVersion", "N/A");
656660
string manualDownloadURLString = version.GetStringValue("DTA", "ManualDownloadURL", string.Empty);
@@ -722,7 +726,7 @@ private static async Task DoVersionCheckAsync()
722726
if (versionString == GameVersion)
723727
{
724728
VersionState = VersionState.UPTODATE;
725-
downloadFile.Delete();
729+
versionFile.Delete();
726730
DoFileIdentifiersUpdatedEvent();
727731

728732
if (AreCustomComponentsOutdated())
@@ -736,7 +740,7 @@ private static async Task DoVersionCheckAsync()
736740
VersionState = VersionState.OUTDATED;
737741
ManualUpdateRequired = true;
738742
ManualDownloadURL = manualDownloadURLString;
739-
downloadFile.Delete();
743+
versionFile.Delete();
740744
DoFileIdentifiersUpdatedEvent();
741745
}
742746
else
@@ -779,7 +783,7 @@ private static async ValueTask ExecuteAfterUpdateScriptAsync()
779783
try
780784
{
781785
string downloadFile = SafePath.CombineFilePath(GamePath, "updateexec");
782-
786+
783787
FileStream fileStream = new FileStream(downloadFile, FileMode.Create, FileAccess.Write, FileShare.None, 4096, FileOptions.Asynchronous);
784788

785789
using (fileStream)
@@ -811,7 +815,7 @@ private static async ValueTask<bool> ExecutePreUpdateScriptAsync()
811815
try
812816
{
813817
string downloadFile = SafePath.CombineFilePath(GamePath, "preupdateexec");
814-
818+
815819
FileStream fileStream = new FileStream(downloadFile, FileMode.Create, FileAccess.Write, FileShare.None, 4096, FileOptions.Asynchronous);
816820

817821
using (fileStream)
@@ -851,7 +855,13 @@ private static void ExecuteScript(string fileName)
851855

852856
try
853857
{
854-
SafePath.DeleteFileIfExists(GamePath, key);
858+
FileInfo fileInfo = SafePath.GetFile(GamePath, key);
859+
860+
if (fileInfo.Exists)
861+
{
862+
fileInfo.IsReadOnly = false;
863+
fileInfo.Delete();
864+
}
855865
}
856866
catch (Exception ex)
857867
{
@@ -869,10 +879,30 @@ private static void ExecuteScript(string fileName)
869879
{
870880
Logger.Log("Updater: " + fileName + ": Renaming file '" + key + "' to '" + newFilename + "'");
871881

872-
FileInfo file = SafePath.GetFile(GamePath, key);
882+
FileInfo srcFile = SafePath.GetFile(GamePath, key);
883+
884+
if (srcFile.Exists)
885+
{
886+
bool isSrcReadOnly = srcFile.IsReadOnly;
887+
srcFile.IsReadOnly = false;
888+
889+
{
890+
FileInfo destFile = SafePath.GetFile(GamePath, newFilename);
891+
if (destFile.Exists)
892+
{
893+
destFile.IsReadOnly = false;
894+
destFile.Delete();
895+
}
896+
}
897+
898+
srcFile.MoveTo(SafePath.CombineFilePath(GamePath, newFilename));
873899

874-
if (file.Exists)
875-
file.MoveTo(SafePath.CombineFilePath(GamePath, newFilename));
900+
if (isSrcReadOnly)
901+
{
902+
FileInfo destFile = SafePath.GetFile(GamePath, newFilename);
903+
destFile.IsReadOnly = true;
904+
}
905+
}
876906
}
877907
catch (Exception ex)
878908
{
@@ -890,10 +920,10 @@ private static void ExecuteScript(string fileName)
890920
{
891921
Logger.Log("Updater: " + fileName + ": Renaming directory '" + key + "' to '" + newDirectoryName + "'");
892922

893-
DirectoryInfo directory = SafePath.GetDirectory(GamePath, key);
923+
DirectoryInfo srcDirectory = SafePath.GetDirectory(GamePath, key);
894924

895-
if (directory.Exists)
896-
directory.MoveTo(SafePath.CombineDirectoryPath(GamePath, newDirectoryName));
925+
if (srcDirectory.Exists)
926+
srcDirectory.MoveTo(SafePath.CombineDirectoryPath(GamePath, newDirectoryName));
897927
}
898928
catch (Exception ex)
899929
{
@@ -928,18 +958,29 @@ private static void ExecuteScript(string fileName)
928958
FileInfo[] files = gameDirectory.GetFiles();
929959
foreach (FileInfo file in files)
930960
{
961+
bool isSrcReadOnly = file.IsReadOnly;
962+
file.IsReadOnly = false;
963+
931964
FileInfo fileToMergeInto = SafePath.GetFile(directoryToMergeInto.FullName, file.Name);
932965
if (fileToMergeInto.Exists)
933966
{
934967
Logger.Log("Updater: " + fileName + ": Destination file '" + directoryNameToMergeInto + "/" + file.Name +
935968
"' exists, removing original source file " + directoryName + "/" + file.Name);
936-
fileToMergeInto.Delete();
969+
970+
// Note: Previously, the incorrect file was deleted as of commit fc939a06ff978b51daa6563eaa15a28cf48319ec.
971+
972+
// Remove the original source file
973+
file.Delete();
937974
}
938975
else
939976
{
940977
Logger.Log("Updater: " + fileName + ": Destination file '" + directoryNameToMergeInto + "/" + file.Name +
941978
"' does not exist, moving original source file " + directoryName + "/" + file.Name);
942979
file.MoveTo(fileToMergeInto.FullName);
980+
981+
// Resume the read-only property
982+
fileToMergeInto.Refresh();
983+
fileToMergeInto.IsReadOnly = isSrcReadOnly;
943984
}
944985
}
945986
}
@@ -959,7 +1000,17 @@ private static void ExecuteScript(string fileName)
9591000
{
9601001
Logger.Log("Updater: " + fileName + ": Deleting directory '" + key + "'");
9611002

962-
SafePath.DeleteDirectoryIfExists(true, GamePath, key);
1003+
DirectoryInfo directoryInfo = SafePath.GetDirectory(GamePath, key);
1004+
if (directoryInfo.Exists)
1005+
{
1006+
// Unset read-only attribute from all files in the directory.
1007+
foreach (FileInfo file in directoryInfo.GetFiles("*", SearchOption.AllDirectories))
1008+
{
1009+
file.IsReadOnly = false;
1010+
}
1011+
1012+
directoryInfo.Delete(true);
1013+
}
9631014
}
9641015
catch (Exception ex)
9651016
{

DTAConfig/OptionPanels/ComponentsPanel.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ private void Btn_LeftClick(object sender, EventArgs e)
147147
{
148148
if (cc.LocalIdentifier == cc.RemoteIdentifier)
149149
{
150+
localFileInfo.IsReadOnly = false;
150151
localFileInfo.Delete();
151152
btn.Text = "Install".L10N("Client:DTAConfig:Install") + $" ({GetSizeString(cc.RemoteSize)})";
152153
return;

0 commit comments

Comments
 (0)