Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revert to .NET Framework #494

Merged
merged 3 commits into from
Feb 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 4 additions & 4 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,20 @@ jobs:
Game: [Ares,TS,YR]

steps:
- uses: actions/checkout@v3.1.0
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Setup .NET Core SDK
uses: actions/setup-dotnet@v3.0.3
uses: actions/setup-dotnet@v4
with:
dotnet-version: '7.x.x'
dotnet-version: '8.x.x'
SadPencil marked this conversation as resolved.
Show resolved Hide resolved

- name: Build ${{matrix.Game}}
run: ./BuildScripts/Build-${{matrix.Game}}.ps1
shell: pwsh

- uses: actions/upload-artifact@v3.1.1
- uses: actions/upload-artifact@v4
name: Upload Artifacts
with:
name: artifacts-${{matrix.Game}}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pr-build-comment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success'
runs-on: ubuntu-22.04
steps:
- uses: actions/github-script@v6.3.1
- uses: actions/github-script@v6
with:
# This snippet is public-domain, taken from
# https://github.com/oprypin/nightly.link/blob/master/.github/workflows/pr-comment.yml
Expand Down
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,11 @@ PublishScripts/
*.nupkg
# NuGet Symbol Packages
*.snupkg

# ... with an exception in References folder
!**/[Rr]eferences/*.nupkg
!**/[Rr]eferences/*.snupkg

# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
Expand Down
9 changes: 7 additions & 2 deletions BuildScripts/Build-Ares.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,14 @@ param($Configuration = "Release")

. $PSScriptRoot\Common.ps1

Build-Project $Configuration Ares UniversalGL net7.0
$Game = "Ares"

Build-Project $Configuration $Game UniversalGL net8.0
if ($IsWindows) {
@('WindowsDX', 'WindowsGL', 'WindowsXNA') | ForEach-Object {
Build-Project $Configuration Ares $_ net7.0-windows
$Engine = $_
@('net48', 'net8.0-windows') | ForEach-Object {
Build-Project $Configuration $Game $Engine $_
}
}
}
9 changes: 7 additions & 2 deletions BuildScripts/Build-TS.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,14 @@ param($Configuration = "Release")

. $PSScriptRoot\Common.ps1

Build-Project $Configuration TS UniversalGL net7.0
$Game = "TS"

Build-Project $Configuration $Game UniversalGL net8.0
if ($IsWindows) {
@('WindowsDX', 'WindowsGL', 'WindowsXNA') | ForEach-Object {
Build-Project $Configuration TS $_ net7.0-windows
$Engine = $_
@('net48', 'net8.0-windows') | ForEach-Object {
Build-Project $Configuration $Game $Engine $_
}
}
}
9 changes: 7 additions & 2 deletions BuildScripts/Build-YR.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,14 @@ param($Configuration = "Release")

. $PSScriptRoot\Common.ps1

Build-Project $Configuration YR UniversalGL net7.0
$Game = "YR"

Build-Project $Configuration $Game UniversalGL net8.0
if ($IsWindows) {
@('WindowsDX', 'WindowsGL', 'WindowsXNA') | ForEach-Object {
Build-Project $Configuration YR $_ net7.0-windows
$Engine = $_
@('net48', 'net8.0-windows') | ForEach-Object {
Build-Project $Configuration $Game $Engine $_
}
}
}
16 changes: 8 additions & 8 deletions BuildScripts/Common.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,21 @@
$RepoRoot = Split-Path $PSScriptRoot -Parent
$ProjectPath = Join-Path $RepoRoot DXMainClient DXMainClient.csproj
$CompiledRoot = Join-Path $RepoRoot Compiled
$EngineMap = @{
$EngineSubFolderMap = @{
'UniversalGL' = 'UniversalGL'
'WindowsDX' = 'Windows'
'WindowsGL' = 'OpenGL'
'WindowsXNA' = 'XNA'
}
$FrameworkBinariesFolderMap = @{
'net48' = 'Binaries'
'net8.0' = 'BinariesNET8'
'net8.0-windows' = 'BinariesNET8'
}

function Build-Project($Configuration, $Game, $Engine, $Framework) {
$Output = Join-Path $CompiledRoot $Game $Output Resources Binaries ($EngineMap[$Engine])
if ($Engine -EQ 'WindowsXNA') {
dotnet publish $ProjectPath --configuration=$Configuration -property:GAME=$Game -property:ENGINE=$Engine --framework=$Framework --output=$Output --arch=x86
}
else {
dotnet publish $ProjectPath --configuration=$Configuration -property:GAME=$Game -property:ENGINE=$Engine --framework=$Framework --output=$Output
}
$Output = Join-Path $CompiledRoot $Game $Output Resources ($FrameworkBinariesFolderMap[$Framework]) ($EngineSubFolderMap[$Engine])
dotnet publish $ProjectPath -c $Configuration -p:GAME=$Game -p:ENGINE=$Engine -f $Framework -o $Output -p:SatelliteResourceLanguages=en -p:AssemblyVersion=$AssemblySemVer -p:FileVersion=$AssemblySemFileVer -p:InformationalVersion=$InformationalVersion $($Engine -EQ 'WindowsXNA' ? '--arch=x86' : '')
if ($LASTEXITCODE) {
throw "Build failed for $Game $Engine $Framework $Configuration"
}
Expand Down
4 changes: 2 additions & 2 deletions BuildScripts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ TargetFramework configurations
For each Engine configuration one or more TargetFrameworks will be build:

UniversalGL:
* net7.0
* net8.0

WindowsDX, WindowsGL & WindowsXNA:
* net7.0-windows
* net48

Overview of the Engine configurations differences:

Expand Down
47 changes: 42 additions & 5 deletions ClientCore/ClientConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using ClientCore.I18N;
using ClientCore.Extensions;

Expand Down Expand Up @@ -237,7 +236,7 @@

public string StatisticsLogFileName => clientDefinitionsIni.GetStringValue(SETTINGS, "StatisticsLogFileName", "DTA.LOG");

public (string Name, string Path) GetThemeInfoFromIndex(int themeIndex) => clientDefinitionsIni.GetStringValue("Themes", themeIndex.ToString(), ",").Split(',').AsTuple2();

Check warning on line 239 in ClientCore/ClientConfiguration.cs

View workflow job for this annotation

GitHub Actions / build-clients (Ares)

The behavior of 'int.ToString()' could vary based on the current user's locale settings. Replace this call in 'ClientConfiguration.GetThemeInfoFromIndex(int)' with a call to 'int.ToString(IFormatProvider)'. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1305)

Check warning on line 239 in ClientCore/ClientConfiguration.cs

View workflow job for this annotation

GitHub Actions / build-clients (TS)

The behavior of 'int.ToString()' could vary based on the current user's locale settings. Replace this call in 'ClientConfiguration.GetThemeInfoFromIndex(int)' with a call to 'int.ToString(IFormatProvider)'. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1305)

Check warning on line 239 in ClientCore/ClientConfiguration.cs

View workflow job for this annotation

GitHub Actions / build-clients (YR)

The behavior of 'int.ToString()' could vary based on the current user's locale settings. Replace this call in 'ClientConfiguration.GetThemeInfoFromIndex(int)' with a call to 'int.ToString(IFormatProvider)'. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1305)

/// <summary>
/// Returns the directory path for a theme, or null if the specified
Expand Down Expand Up @@ -283,17 +282,17 @@
{
// the syntax is GameFileX=path/to/source.file,path/to/destination.file[,checked]
string value = clientDefinitionsIni.GetStringValue(TRANSLATIONS, $"GameFile{i}", string.Empty);
string[] parts = value.Split(',', StringSplitOptions.TrimEntries);
string[] parts = value.Split(',', StringSplitOptions.RemoveEmptyEntries).Select(s => s.Trim()).ToArray();

// fail explicitly if the syntax is wrong
if (parts.Length is < 2 or > 3
|| (parts.Length == 3 && parts[2].ToUpperInvariant() != "CHECKED"))

Check warning on line 289 in ClientCore/ClientConfiguration.cs

View workflow job for this annotation

GitHub Actions / build-clients (Ares)

Prefer using 'string.Equals(string, StringComparison)' to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1862)

Check warning on line 289 in ClientCore/ClientConfiguration.cs

View workflow job for this annotation

GitHub Actions / build-clients (TS)

Prefer using 'string.Equals(string, StringComparison)' to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1862)

Check warning on line 289 in ClientCore/ClientConfiguration.cs

View workflow job for this annotation

GitHub Actions / build-clients (YR)

Prefer using 'string.Equals(string, StringComparison)' to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1862)
{
throw new IniParseException($"Invalid syntax for value of GameFile{i}! " +
$"Expected path/to/source.file,path/to/destination.file[,checked], read {value}.");
}

bool isChecked = parts.Length == 3 && parts[2].ToUpperInvariant() == "CHECKED";

Check warning on line 295 in ClientCore/ClientConfiguration.cs

View workflow job for this annotation

GitHub Actions / build-clients (Ares)

Prefer using 'string.Equals(string, StringComparison)' to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1862)

Check warning on line 295 in ClientCore/ClientConfiguration.cs

View workflow job for this annotation

GitHub Actions / build-clients (TS)

Prefer using 'string.Equals(string, StringComparison)' to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1862)

Check warning on line 295 in ClientCore/ClientConfiguration.cs

View workflow job for this annotation

GitHub Actions / build-clients (YR)

Prefer using 'string.Equals(string, StringComparison)' to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1862)

gameFiles.Add(new(Source: parts[0], Target: parts[1], isChecked));
}
Expand Down Expand Up @@ -382,15 +381,53 @@

public OSVersion GetOperatingSystemVersion()
{
#if NETFRAMEWORK
// OperatingSystem.IsWindowsVersionAtLeast() is the preferred API but is not supported on earlier .NET versions
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
{
Version osVersion = Environment.OSVersion.Version;

if (osVersion.Major <= 4)
return OSVersion.UNKNOWN;

if (osVersion.Major == 5)
return OSVersion.WINXP;

if (osVersion.Major == 6 && osVersion.Minor == 0)
return OSVersion.WINVISTA;

if (osVersion.Major == 6 && osVersion.Minor <= 1)
return OSVersion.WIN7;
SadPencil marked this conversation as resolved.
Show resolved Hide resolved

return OSVersion.WIN810;
}

if (ProgramConstants.ISMONO)
return OSVersion.UNIX;

// http://mono.wikia.com/wiki/Detecting_the_execution_platform
int p = (int)Environment.OSVersion.Platform;
if (p == 4 || p == 6 || p == 128)
return OSVersion.UNIX;

return OSVersion.UNKNOWN;
#else
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
if (OperatingSystem.IsWindowsVersionAtLeast(6, 3))
if (OperatingSystem.IsWindowsVersionAtLeast(6, 2))
return OSVersion.WIN810;

return OSVersion.WIN7;
else if (OperatingSystem.IsWindowsVersionAtLeast(6, 1))
return OSVersion.WIN7;
else if (OperatingSystem.IsWindowsVersionAtLeast(6, 0))
return OSVersion.WINVISTA;
else if (OperatingSystem.IsWindowsVersionAtLeast(5, 0))
return OSVersion.WINXP;
else
return OSVersion.UNKNOWN;
}

return OSVersion.UNIX;
#endif
}
}

Expand Down
10 changes: 6 additions & 4 deletions ClientCore/ClientCore.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<Description>CnCNet Client Core Library</Description>
<Company>CnCNet</Company>
<Product>CnCNet Client</Product>
<Copyright>Copyright © CnCNet, Rampastring 2011-2022</Copyright>
<Copyright>Copyright © CnCNet, Rampastring 2011-2024</Copyright>
SadPencil marked this conversation as resolved.
Show resolved Hide resolved
<Trademark>CnCNet</Trademark>
<Version>2.0.0.3</Version>
<FileVersion>2.0.0.3</FileVersion>
Expand Down Expand Up @@ -50,9 +50,11 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Rampastring.Tools" Version="2.0.4" />
<PackageReference Include="Rampastring.XNAUI.$(Engine)" Version="2.3.8" Condition="'!$(Configuration.Contains(Debug))'" />
<PackageReference Include="Rampastring.XNAUI.$(Engine).Debug" Version="2.3.8" Condition="'$(Configuration.Contains(Debug))'" />
<!-- TODO: update version after this package targets .NET 8. -->
<PackageReference Include="Rampastring.Tools" Version="2.0.6-local-397fda5" />
<!-- TODO: update version after this package targets .NET 8. -->
Metadorius marked this conversation as resolved.
Show resolved Hide resolved
<PackageReference Include="Rampastring.XNAUI.$(Engine)" Version="2.3.20-local-2c977ab" Condition="'!$(Configuration.Contains(Debug))'" />
<PackageReference Include="Rampastring.XNAUI.$(Engine).Debug" Version="2.3.20-local-2c977ab" Condition="'$(Configuration.Contains(Debug))'" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="7.0.0" />
</ItemGroup>
<ItemGroup>
Expand Down
14 changes: 7 additions & 7 deletions ClientCore/Extensions/StringExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ public static string ToIniString(this string raw)
throw new ArgumentException($"The string contains an illegal character sequence! ({ESCAPED_SEMICOLON})");

return raw
.Replace(ProgramConstants.INI_NEWLINE_PATTERN, ESCAPED_INI_NEWLINE_PATTERN, StringComparison.InvariantCulture)
.Replace(";", ESCAPED_SEMICOLON, StringComparison.InvariantCulture)
.Replace(Environment.NewLine, "\n", StringComparison.InvariantCulture)
.Replace("\n", ProgramConstants.INI_NEWLINE_PATTERN, StringComparison.InvariantCulture);
.Replace(ProgramConstants.INI_NEWLINE_PATTERN, ESCAPED_INI_NEWLINE_PATTERN)
.Replace(";", ESCAPED_SEMICOLON)
.Replace(Environment.NewLine, "\n")
.Replace("\n", ProgramConstants.INI_NEWLINE_PATTERN);
}

/// <summary>
Expand All @@ -54,9 +54,9 @@ public static string ToIniString(this string raw)
public static string FromIniString(this string iniString)
{
return iniString
.Replace(ESCAPED_INI_NEWLINE_PATTERN, ProgramConstants.INI_NEWLINE_PATTERN, StringComparison.InvariantCulture)
.Replace(ESCAPED_SEMICOLON, ";", StringComparison.InvariantCulture)
.Replace(ProgramConstants.INI_NEWLINE_PATTERN, Environment.NewLine, StringComparison.InvariantCulture);
.Replace(ESCAPED_INI_NEWLINE_PATTERN, ProgramConstants.INI_NEWLINE_PATTERN)
.Replace(ESCAPED_SEMICOLON, ";")
.Replace(ProgramConstants.INI_NEWLINE_PATTERN, Environment.NewLine);
}

/// <summary>
Expand Down
3 changes: 2 additions & 1 deletion ClientCore/I18N/Translation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ public Translation(string localeCode)
public Translation(IniFile ini, string localeCode)
: this(localeCode)
{
ArgumentNullException.ThrowIfNull(ini);
if (ini is null)
throw new ArgumentNullException(nameof(ini));

IniSection metadataSection = ini.GetSection(METADATA_SECTION);
Name = metadataSection?.GetStringValue(nameof(Name), string.Empty);
Expand Down
58 changes: 52 additions & 6 deletions ClientCore/ProgramConstants.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Reflection;
#if WINFORMS
Expand All @@ -20,11 +21,7 @@ public static class ProgramConstants

public static readonly string StartupPath = SafePath.CombineDirectoryPath(new FileInfo(StartupExecutable).Directory.FullName);

#if DEBUG
public static readonly string GamePath = SafePath.CombineDirectoryPath(SafePath.GetDirectory(StartupPath).Parent.Parent.FullName);
#else
public static readonly string GamePath = SafePath.CombineDirectoryPath(SafePath.GetDirectory(StartupPath).Parent.Parent.Parent.FullName);
#endif
public static readonly string GamePath = SafePath.CombineDirectoryPath(GetGamePath(StartupPath));

public static string ClientUserFilesPath => SafePath.CombineDirectoryPath(GamePath, "Client");

Expand Down Expand Up @@ -62,6 +59,15 @@ public static class ProgramConstants

public static readonly Encoding LAN_ENCODING = Encoding.UTF8;

#if NETFRAMEWORK
private static bool? isMono;

/// <summary>
/// Gets a value whether or not the application is running under Mono. Uses lazy loading and caching.
/// </summary>
public static bool ISMONO => isMono ??= Type.GetType("Mono.Runtime") != null;
#endif

public static string GAME_VERSION = "Undefined";
private static string PlayerName = "No name";

Expand Down Expand Up @@ -115,17 +121,57 @@ public static string GetAILevelName(int aiLevel)
/// <summary>
/// Gets or sets the action to perform to notify the user of an error.
/// </summary>
public static Action<string, string, bool> DisplayErrorAction { get; set; } = (title, error, exit) =>
public static Action<string, string, bool> DisplayErrorAction { get; set; } = DefaultDisplayErrorAction;

public static Action<string, string, bool> DefaultDisplayErrorAction = (title, error, exit) =>
{
Logger.Log(FormattableString.Invariant($"{(title is null ? null : title + Environment.NewLine + Environment.NewLine)}{error}"));
#if WINFORMS
#if NETFRAMEWORK
MessageBox.Show(error, title, MessageBoxButtons.OK);
#else
TaskDialog.ShowDialog(new() { Caption = title, Heading = error });
#endif
#else
ProcessLauncher.StartShellProcess(LogFileName);
#endif

if (exit)
Environment.Exit(1);
};

/// <summary>
/// This method finds the "Resources" directory by traversing the directory tree upwards from the startup path.
/// </summary>
/// <remarks>
/// This method is needed by both ClientCore and DXMainClient. However, since it is usually called at the very beginning,
/// where DXMainClient could not refer to ClientCore, this method is copied to both projects.
/// Remember to keep <see cref="ClientCore.ProgramConstants.SearchResourcesDir"/> and <see cref="DTAClient.Program.SearchResourcesDir"/> consistent if you have modified its source codes.
/// </remarks>
private static string SearchResourcesDir(string startupPath)
{
DirectoryInfo currentDir = new(startupPath);
for (int i = 0; i < 3; i++)
{
// Determine if currentDir is the "Resources" folder
if (currentDir.Name.ToLowerInvariant() == "Resources".ToLowerInvariant())
return currentDir.FullName;

// Additional check. This makes developers to debug the client inside Visual Studio a little bit easier.
DirectoryInfo resourcesDir = currentDir.GetDirectories("Resources", SearchOption.TopDirectoryOnly).FirstOrDefault();
if (resourcesDir is not null)
return resourcesDir.FullName;

currentDir = currentDir.Parent;
}

throw new Exception("Could not find Resources directory.");
}

private static string GetGamePath(string startupPath)
{
string resourceDir = SearchResourcesDir(startupPath);
return new DirectoryInfo(resourceDir).Parent.FullName;
}
}
}
2 changes: 1 addition & 1 deletion ClientGUI/ClientGUI.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<Description>CnCNet Client UI Library</Description>
<Company>CnCNet</Company>
<Product>CnCNet Client</Product>
<Copyright>Copyright © CnCNet, Rampastring 2011-2022</Copyright>
<Copyright>Copyright © CnCNet, Rampastring 2011-2024</Copyright>
<Trademark>CnCNet</Trademark>
<Version>2.1.0.1</Version>
<FileVersion>2.1.0.1</FileVersion>
Expand Down
Loading
Loading