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

Network stack update #383

Closed
wants to merge 109 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
109 commits
Select commit Hold shift + click to select a range
a68b5f6
Start work on version 3 tunnel support
Rampastring Jun 22, 2019
8cd2318
Update TunnelHandler, add TunneledPlayerConnection
Rampastring Jun 23, 2019
f92f33f
Add GameTunnelHandler
Rampastring Jun 23, 2019
0592c6c
Implement starting games with V3 tunnels, testing TODO
Rampastring Jun 23, 2019
5e00f3a
Fix CTCP string command handler not properly checking that the messag…
Rampastring Jun 24, 2019
3156a68
Fix bugs related to starting games with v3 tunnel connections, send t…
Rampastring Jun 24, 2019
82eecd1
Improve format of "total time played" and "average game length" in th…
Rampastring Jun 24, 2019
96aec49
Fix a bunch of issues related to starting games using v3 tunnels
Rampastring Jun 25, 2019
7f4ef83
Fix more v3 tunnel issues
Rampastring Jun 25, 2019
496f546
Rebase fix
Rans4ckeR Aug 14, 2022
8e43728
Rebase cleanup, remove V3 tunnel login logic
Rans4ckeR Aug 14, 2022
abab4fa
Fix V3 tunnel player port assignment
Rans4ckeR Aug 15, 2022
94c416b
Logging
Rans4ckeR Aug 15, 2022
480ec20
Parse IPv6 & IPv4 tunnel addresses from master server, support IPv6 &…
Rans4ckeR Aug 15, 2022
0a09e71
V3 tunnel fixes
Rans4ckeR Aug 16, 2022
bc2304a
Cleanup
Rans4ckeR Aug 17, 2022
511ac5e
Ignore socket error when game not loaded yet
Rans4ckeR Aug 19, 2022
8451250
Use game DualMode socket
Rans4ckeR Aug 19, 2022
fa939d2
Fix tunnel selection window
Rans4ckeR Aug 21, 2022
a425644
Replace obsolete WebClient with HttpClient, IRC & LAN IPv6 support wi…
Rans4ckeR Aug 20, 2022
5d895ac
LAN connection fixes
Rans4ckeR Aug 20, 2022
f559825
Fix LAN game connections
Rans4ckeR Aug 21, 2022
9c0a3c1
Prevent possible runtime errors with missing callback arguments
Rans4ckeR Aug 21, 2022
3fe7c32
Cleanup
Rans4ckeR Aug 23, 2022
6afccc9
Use Task.Run()
Rans4ckeR Aug 26, 2022
668a813
Use https requests (HTTP/2)
Rans4ckeR Sep 2, 2022
b169c9a
Tunnel IPv6/IPv4 selection
Rans4ckeR Sep 12, 2022
ba26e86
Fix IRC Exception when user *.GameSurge.net sets MODE
Rans4ckeR Sep 13, 2022
eaf761c
Fix IRC disconnect
Rans4ckeR Sep 13, 2022
bceb8f5
Update IRC server selection
Rans4ckeR Sep 13, 2022
65e28b7
Fix LAN lobby crash when no map selected
Rans4ckeR Sep 23, 2022
4b27b0b
Don't send LAN host player joined using UI thread
Rans4ckeR Sep 23, 2022
0eb89e8
Fix net48 build
Rans4ckeR Sep 23, 2022
e38f019
Rebase fix
Rans4ckeR Nov 22, 2022
0830799
Remove net48 code after net7 rebase
Rans4ckeR Nov 25, 2022
3edfa0d
Use SocketsHttpHandler instead of HttpClientHandler
Rans4ckeR Nov 26, 2022
61453fc
Clean up Task Exception handling
Rans4ckeR Nov 26, 2022
45e4b14
Update Task exception handling
Rans4ckeR Nov 26, 2022
cb7b574
Update tunnel api url
Rans4ckeR Nov 26, 2022
e985f18
Saved game constants
Rans4ckeR Nov 26, 2022
3f85b94
Exception logging
Rans4ckeR Nov 26, 2022
3e7b37c
Group network commands
Rans4ckeR Nov 27, 2022
8b73800
Dynamic V3 tunnel selection
Rans4ckeR Nov 29, 2022
198ae18
Add chat command for dynamic tunnels
Rans4ckeR Nov 29, 2022
b42bbed
Tunnel switching and matching
Rans4ckeR Nov 29, 2022
6ad7f95
Fix LAN lobbies broadcast/discovery with multiple network interfaces
Rans4ckeR Dec 2, 2022
3946539
Support P2P and UPnP port forwarding
Rans4ckeR Dec 3, 2022
fe5bbc2
Fix after rebase
Rans4ckeR Dec 3, 2022
eb4a6fb
Cleanup
Rans4ckeR Dec 3, 2022
04a8f07
Rebase fix
Rans4ckeR Dec 3, 2022
5a1072b
Update P2P connection handling, use ValueTasks
Rans4ckeR Dec 6, 2022
949144b
CnCNetGameLobby Dispose
Rans4ckeR Dec 6, 2022
7c8734a
Use Tasks instead of Threads
Rans4ckeR Dec 7, 2022
e010200
Use Tasks instead of Threads
Rans4ckeR Dec 7, 2022
3e87d9b
Update P2P handling
Rans4ckeR Dec 7, 2022
352a1d9
Handle remote player disconnects
Rans4ckeR Dec 10, 2022
60e3436
Handle P2P direct public IP to public IP connections
Rans4ckeR Dec 10, 2022
670629d
P2P ping cleanup
Rans4ckeR Dec 11, 2022
8670570
Add P2P STUN
Rans4ckeR Dec 11, 2022
a87b202
P2P STUN port mapping and keep alive
Rans4ckeR Dec 11, 2022
6722a88
Cleanup
Rans4ckeR Dec 12, 2022
e7b4f2c
Refactor
Rans4ckeR Dec 13, 2022
d1e55a8
HttpClient handling
Rans4ckeR Dec 13, 2022
2b0d575
Apply ConfigureAwait()
Rans4ckeR Dec 14, 2022
75cbe75
Async file I/O, stream V3 replay data to disk
Rans4ckeR Dec 18, 2022
021c3e0
Game recording cleanup
Rans4ckeR Dec 18, 2022
de77ef8
Don't parse statistics on UI thread
Rans4ckeR Dec 20, 2022
f3b1886
Prevent some exceptions
Rans4ckeR Dec 21, 2022
670be66
P2P: don't fail on UPnP device unavailable services
Rans4ckeR Dec 21, 2022
2000bf5
P2P logging
Rans4ckeR Dec 21, 2022
8fe71cb
V3 performance & P2P STUN improvements
Rans4ckeR Dec 28, 2022
2ae95e2
V3 refactoring, P2P improvements
Rans4ckeR Dec 30, 2022
91ff05b
Fix Release build
Rans4ckeR Dec 30, 2022
f3d0375
P2P: Handle blocked ping
Rans4ckeR Dec 30, 2022
2540b75
Fix build
Rans4ckeR Dec 30, 2022
b1d4bc2
UPnP Refactoring
Rans4ckeR Dec 31, 2022
7003bbd
Update tunnel list uri
Rans4ckeR Dec 31, 2022
13f2635
UPnP cleanup
Rans4ckeR Dec 31, 2022
e627b6f
Update year
Rans4ckeR Jan 1, 2023
5810228
Socket timeout handling, update dependencies
Rans4ckeR Jan 3, 2023
7868567
Fix tunnel start race condition
Rans4ckeR Jan 5, 2023
81b7e2f
IPv6 cross-platform & multi-adapter improvements
Rans4ckeR Jan 6, 2023
0682b0b
Handle tunnel race condition
Rans4ckeR Jan 7, 2023
ead24a9
LAN lobby multi-adapter improvements
Rans4ckeR Jan 7, 2023
80ec54d
Fix LANLobby game closing
Rans4ckeR Jan 7, 2023
d25099c
IPv6/IPv4 internet detection & P2P improvements
Rans4ckeR Jan 8, 2023
02390fe
Fix debug build
Rans4ckeR Jan 8, 2023
d2e30a5
Fix tunnel - game race condition
Rans4ckeR Jan 9, 2023
ab83bf8
Tunnel parsing speedup
Rans4ckeR Jan 9, 2023
8ad96dc
Fix extracting map preview
Rans4ckeR Jan 10, 2023
30b3064
Update master server url
Rans4ckeR Jan 13, 2023
7d45c61
Add UPnP RemoteCertificateValidationCallback
Rans4ckeR Jan 16, 2023
8585f3d
P2P: UPnP SSDP on all interfaces
Rans4ckeR Jan 20, 2023
3920e29
Update packages
Rans4ckeR Jan 24, 2023
1fed956
MultipleInstanceMode mutex fix and some cleanups
Rans4ckeR Feb 13, 2023
5703822
Update packages & sh files
Rans4ckeR Feb 18, 2023
26f1136
Map preview clean up
Rans4ckeR Feb 22, 2023
0addc51
Update packages
Rans4ckeR Jun 18, 2023
78b76a9
Fix merge
Rans4ckeR Jun 19, 2023
81c6eca
Merge cleanup
Rans4ckeR Jun 19, 2023
70e11ad
Fix build
Rans4ckeR Jun 19, 2023
a229ed4
UPnP fix
Rans4ckeR Jun 19, 2023
ebb7ad3
Delete CUSTOM_MAPS_CACHE on parse error
Rans4ckeR Jun 19, 2023
4854d09
Update packages
Rans4ckeR Jul 2, 2023
a90a220
Fix TranslationNotifierGenerator for XNA x86 build
Rans4ckeR Jul 2, 2023
11dcb4e
Fix CUSTOM_MAPS_CACHE writing
Rans4ckeR Jul 2, 2023
a012e44
Update packages
Rans4ckeR Aug 18, 2023
cc96c17
Clean up dependencies
Rans4ckeR Sep 2, 2023
82b65fe
Update build
Rans4ckeR Sep 2, 2023
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,514 changes: 1,172 additions & 342 deletions .editorconfig

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
###############################################################################
* text=auto
*.ps1 eol=lf
*.sh eol=lf

###############################################################################
# Set default behavior for command prompt diff.
Expand Down
6 changes: 3 additions & 3 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@v3.6.0
with:
fetch-depth: 0

- name: Setup .NET Core SDK
uses: actions/setup-dotnet@v3.0.3
uses: actions/setup-dotnet@v3.2.0
with:
dotnet-version: '7.x.x'

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

- uses: actions/[email protected].1
- uses: actions/[email protected].2
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.4.1
with:
# This snippet is public-domain, taken from
# https://github.com/oprypin/nightly.link/blob/master/.github/workflows/pr-comment.yml
Expand Down
4 changes: 2 additions & 2 deletions BuildScripts/Common.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ $EngineMap = @{
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
dotnet publish $ProjectPath -c $Configuration -p:GAME=$Game -p:ENGINE=$Engine -f $Framework -o $Output -p:SatelliteResourceLanguages=en -a x86
}
else {
dotnet publish $ProjectPath --configuration=$Configuration -property:GAME=$Game -property:ENGINE=$Engine --framework=$Framework --output=$Output
dotnet publish $ProjectPath -c $Configuration -p:GAME=$Game -p:ENGINE=$Engine -f $Framework -o $Output -p:SatelliteResourceLanguages=en
}
if ($LASTEXITCODE) {
throw "Build failed for $Game $Engine $Framework $Configuration"
Expand Down
19 changes: 6 additions & 13 deletions ClientCore/ClientConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Collections.Generic;

Check warning on line 7 in ClientCore/ClientConfiguration.cs

View workflow job for this annotation

GitHub Actions / build-clients (Ares)

The using directive for 'System.Collections.Generic' appeared previously in this namespace

Check warning on line 7 in ClientCore/ClientConfiguration.cs

View workflow job for this annotation

GitHub Actions / build-clients (TS)

The using directive for 'System.Collections.Generic' appeared previously in this namespace

Check warning on line 7 in ClientCore/ClientConfiguration.cs

View workflow job for this annotation

GitHub Actions / build-clients (YR)

The using directive for 'System.Collections.Generic' appeared previously in this namespace
using ClientCore.I18N;
using ClientCore.Extensions;

Expand All @@ -15,7 +15,6 @@
private const string GENERAL = "General";
private const string AUDIO = "Audio";
private const string SETTINGS = "Settings";
private const string LINKS = "Links";
private const string TRANSLATIONS = "Translations";

private const string CLIENT_SETTINGS = "DTACnCNetClient.ini";
Expand Down Expand Up @@ -53,14 +52,7 @@
/// <returns>The object of the ClientConfiguration class.</returns>
public static ClientConfiguration Instance
{
get
{
if (_instance == null)
{
_instance = new ClientConfiguration();
}
return _instance;
}
get { return _instance ??= new ClientConfiguration(); }
}

public void RefreshSettings()
Expand Down Expand Up @@ -190,7 +182,7 @@

public int MaximumRenderHeight => clientDefinitionsIni.GetIntValue(SETTINGS, "MaximumRenderHeight", 800);

public string[] RecommendedResolutions => clientDefinitionsIni.GetStringValue(SETTINGS, "RecommendedResolutions", "1280x720,2560x1440,3840x2160").Split(',');

Check warning on line 185 in ClientCore/ClientConfiguration.cs

View workflow job for this annotation

GitHub Actions / build-clients (TS)

Properties should not return arrays (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1819)

Check warning on line 185 in ClientCore/ClientConfiguration.cs

View workflow job for this annotation

GitHub Actions / build-clients (YR)

Properties should not return arrays (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1819)

public string WindowTitle => clientDefinitionsIni.GetStringValue(SETTINGS, "WindowTitle", string.Empty)
.L10N("INI:ClientDefinitions:WindowTitle");
Expand All @@ -209,15 +201,15 @@

public string LongGameName => clientDefinitionsIni.GetStringValue(SETTINGS, "LongGameName", "Tiberian Sun");

public string LongSupportURL => clientDefinitionsIni.GetStringValue(SETTINGS, "LongSupportURL", "http://www.moddb.com/members/rampastring");
public string LongSupportURL => clientDefinitionsIni.GetStringValue(SETTINGS, "LongSupportURL", $"{Uri.UriSchemeHttps}://www.moddb.com/members/rampastring");

Check warning on line 204 in ClientCore/ClientConfiguration.cs

View workflow job for this annotation

GitHub Actions / build-clients (TS)

Change the type of property 'ClientConfiguration.LongSupportURL' from 'string' to 'System.Uri' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1056)

Check warning on line 204 in ClientCore/ClientConfiguration.cs

View workflow job for this annotation

GitHub Actions / build-clients (YR)

Change the type of property 'ClientConfiguration.LongSupportURL' from 'string' to 'System.Uri' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1056)

public string ShortSupportURL => clientDefinitionsIni.GetStringValue(SETTINGS, "ShortSupportURL", "www.moddb.com/members/rampastring");

Check warning on line 206 in ClientCore/ClientConfiguration.cs

View workflow job for this annotation

GitHub Actions / build-clients (TS)

Change the type of property 'ClientConfiguration.ShortSupportURL' from 'string' to 'System.Uri' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1056)

Check warning on line 206 in ClientCore/ClientConfiguration.cs

View workflow job for this annotation

GitHub Actions / build-clients (YR)

Change the type of property 'ClientConfiguration.ShortSupportURL' from 'string' to 'System.Uri' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1056)

public string ChangelogURL => clientDefinitionsIni.GetStringValue(SETTINGS, "ChangelogURL", "http://www.moddb.com/mods/the-dawn-of-the-tiberium-age/tutorials/change-log");
public string ChangelogURL => clientDefinitionsIni.GetStringValue(SETTINGS, "ChangelogURL", $"{Uri.UriSchemeHttps}://www.moddb.com/mods/the-dawn-of-the-tiberium-age/tutorials/change-log");

Check warning on line 208 in ClientCore/ClientConfiguration.cs

View workflow job for this annotation

GitHub Actions / build-clients (TS)

Change the type of property 'ClientConfiguration.ChangelogURL' from 'string' to 'System.Uri' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1056)

Check warning on line 208 in ClientCore/ClientConfiguration.cs

View workflow job for this annotation

GitHub Actions / build-clients (YR)

Change the type of property 'ClientConfiguration.ChangelogURL' from 'string' to 'System.Uri' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1056)

public string CreditsURL => clientDefinitionsIni.GetStringValue(SETTINGS, "CreditsURL", "http://www.moddb.com/mods/the-dawn-of-the-tiberium-age/tutorials/credits#Rampastring");
public string CreditsURL => clientDefinitionsIni.GetStringValue(SETTINGS, "CreditsURL", $"{Uri.UriSchemeHttps}://www.moddb.com/mods/the-dawn-of-the-tiberium-age/tutorials/credits#Rampastring");

Check warning on line 210 in ClientCore/ClientConfiguration.cs

View workflow job for this annotation

GitHub Actions / build-clients (TS)

Change the type of property 'ClientConfiguration.CreditsURL' from 'string' to 'System.Uri' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1056)

Check warning on line 210 in ClientCore/ClientConfiguration.cs

View workflow job for this annotation

GitHub Actions / build-clients (YR)

Change the type of property 'ClientConfiguration.CreditsURL' from 'string' to 'System.Uri' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1056)

public string ManualDownloadURL => clientDefinitionsIni.GetStringValue(SETTINGS, "ManualDownloadURL", string.Empty);

Check warning on line 212 in ClientCore/ClientConfiguration.cs

View workflow job for this annotation

GitHub Actions / build-clients (TS)

Change the type of property 'ClientConfiguration.ManualDownloadURL' from 'string' to 'System.Uri' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1056)

Check warning on line 212 in ClientCore/ClientConfiguration.cs

View workflow job for this annotation

GitHub Actions / build-clients (YR)

Change the type of property 'ClientConfiguration.ManualDownloadURL' from 'string' to 'System.Uri' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1056)

public string FinalSunIniPath => SafePath.CombineFilePath(clientDefinitionsIni.GetStringValue(SETTINGS, "FSIniPath", SafePath.CombineFilePath("FinalSun", "FinalSun.ini")));

Expand Down Expand Up @@ -400,7 +392,8 @@
/// </summary>
public class ClientConfigurationException : Exception
{
public ClientConfigurationException(string message) : base(message)
public ClientConfigurationException(string message, Exception ex = null)
: base(message, ex)
{
}
}
Expand Down
13 changes: 4 additions & 9 deletions ClientCore/ClientCore.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,8 @@
<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-2023</Copyright>
<Trademark>CnCNet</Trademark>
<Version>2.0.0.3</Version>
<FileVersion>2.0.0.3</FileVersion>
<InformationalVersion>2.0.0.3</InformationalVersion>
<AssemblyName>ClientCore</AssemblyName>
<RootNamespace>ClientCore</RootNamespace>
</PropertyGroup>
Expand Down Expand Up @@ -46,14 +43,12 @@
<EmbeddedResource Include="Resources\yricon.png" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="GitVersion.MsBuild" Version="5.11.1">
<PackageReference Include="GitVersion.MsBuild" Version="5.12.0">
<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))'" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="7.0.0" />
<PackageReference Include="Rampastring.XNAUI.$(Engine)" Version="2.3.10" Condition="'!$(Configuration.Contains(Debug))'" />
<PackageReference Include="Rampastring.XNAUI.$(Engine).Debug" Version="2.3.10" Condition="'$(Configuration.Contains(Debug))'" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\TranslationNotifierGenerator\TranslationNotifierGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
Expand Down
4 changes: 2 additions & 2 deletions ClientCore/CnCNet5/NameValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public static string IsNameValid(string name)
if (profanityFilter.IsOffensive(name))
return "Please enter a name that is less offensive.".L10N("Client:ClientCore:NameOffensive");

if (int.TryParse(name.Substring(0, 1), out _))
if (int.TryParse(name[..1], out _))
return "The first character in the player name cannot be a number.".L10N("Client:ClientCore:NameFirstIsNumber");

if (name[0] == '-')
Expand Down Expand Up @@ -59,7 +59,7 @@ public static string GetValidOfflineName(string name)
string validName = new string(name.Trim().Where(c => !disallowedCharacters.Contains(c)).ToArray());

if (validName.Length > ClientConfiguration.Instance.MaxNameLength)
return validName.Substring(0, ClientConfiguration.Instance.MaxNameLength);
return validName[..ClientConfiguration.Instance.MaxNameLength];

return validName;
}
Expand Down
19 changes: 8 additions & 11 deletions ClientCore/Extensions/EnumExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,18 @@ namespace ClientCore.Extensions
{
public static class EnumExtensions
{
public static T Next<T>(this T src) where T : Enum
public static T Next<T>(this T src)
where T : Enum
{
T[] Arr = GetValues(src);
int nextIndex = Array.IndexOf(Arr, src) + 1;
return Arr.Length == nextIndex ? Arr[0] : Arr[nextIndex];
T[] values = GetValues(src);
int nextIndex = Array.IndexOf(values, src) + 1;
return values.Length == nextIndex ? values[0] : values[nextIndex];
}

public static T First<T>(this T src) where T : Enum
{
return GetValues(src)[0];
}

private static T[] GetValues<T>(T src) where T : Enum
private static T[] GetValues<T>(T src)
where T : Enum
{
return (T[])Enum.GetValues(src.GetType());
}
}
}
}
8 changes: 4 additions & 4 deletions ClientCore/Extensions/StringExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@ public static string GetLink(this string text)
if (string.IsNullOrWhiteSpace(text))
return null;

int index = text.IndexOf("http://", StringComparison.Ordinal);
int index = text.IndexOf($"{Uri.UriSchemeHttp}://", StringComparison.Ordinal);
if (index == -1)
index = text.IndexOf("ftp://", StringComparison.Ordinal);
index = text.IndexOf($"{Uri.UriSchemeFtp}://", StringComparison.Ordinal);
if (index == -1)
index = text.IndexOf("https://", StringComparison.Ordinal);
index = text.IndexOf($"{Uri.UriSchemeHttps}://", StringComparison.Ordinal);

if (index == -1)
return null; // No link found

string link = text.Substring(index);
string link = text[index..];
return link.Split(' ')[0]; // Nuke any words coming after the link
}

Expand Down
113 changes: 113 additions & 0 deletions ClientCore/Extensions/TaskExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace ClientCore.Extensions;

public static class TaskExtensions
{
/// <summary>
/// Runs a <see cref="Task"/> and guarantees all exceptions are caught and handled even when the <see cref="Task"/> is not directly awaited.
/// </summary>
/// <param name="task">The <see cref="Task"/> who's exceptions will be handled.</param>
/// <param name="continueOnCapturedContext">true to attempt to marshal the continuation back to the original context captured; otherwise, false.</param>
/// <returns>Returns a <see cref="Task"/> that awaited and handled the original <paramref name="task"/>.</returns>
public static async Task HandleTask(this Task task, bool continueOnCapturedContext = false)
{
try
{
await task.ConfigureAwait(continueOnCapturedContext);
}
catch (Exception ex)
{
ProgramConstants.HandleException(ex);
}
}

/// <summary>
/// Runs a <see cref="Task"/> and guarantees all exceptions are caught and handled even when the <see cref="Task"/> is not directly awaited.
/// </summary>
/// <typeparam name="T">The type of <paramref name="task"/>'s return value.</typeparam>
/// <param name="task">The <see cref="Task"/> who's exceptions will be handled.</param>
/// <param name="continueOnCapturedContext">true to attempt to marshal the continuation back to the original context captured; otherwise, false.</param>
/// <returns>Returns a <see cref="Task"/> that awaited and handled the original <paramref name="task"/>.</returns>
public static async Task<T> HandleTask<T>(this Task<T> task, bool continueOnCapturedContext = false)
{
try
{
return await task.ConfigureAwait(continueOnCapturedContext);
}
catch (Exception ex)
{
ProgramConstants.HandleException(ex);
}

return default;
}

/// <summary>
/// Executes a list of tasks and waits for all of them to complete and throws an <see cref="AggregateException"/> containing all exceptions from all tasks.
/// When using <see cref="Task.WhenAll(IEnumerable{Task})"/> only the first thrown exception from a single <see cref="Task"/> may be observed.
/// </summary>
/// <typeparam name="T">The type of <paramref name="tasks"/>'s return value.</typeparam>
/// <param name="tasks">The list of <see cref="Task"/>s who's exceptions will be handled.</param>
/// <param name="continueOnCapturedContext">true to attempt to marshal the continuation back to the original context captured; otherwise, false.</param>
/// <returns>Returns a <see cref="Task"/> that awaited and handled the original <paramref name="tasks"/>.</returns>
public static async Task<T[]> WhenAllSafe<T>(IEnumerable<Task<T>> tasks, bool continueOnCapturedContext = false)
{
var whenAllTask = Task.WhenAll(tasks);

try
{
return await whenAllTask.ConfigureAwait(continueOnCapturedContext);
}
catch
{
if (whenAllTask.Exception is null)
throw;

throw whenAllTask.Exception;
}
}

/// <summary>
/// Executes a list of tasks and waits for all of them to complete and throws an <see cref="AggregateException"/> containing all exceptions from all tasks.
/// When using <see cref="Task.WhenAll(IEnumerable{Task})"/> only the first thrown exception from a single <see cref="Task"/> may be observed.
/// </summary>
/// <param name="tasks">The list of <see cref="Task"/>s who's exceptions will be handled.</param>
/// <param name="continueOnCapturedContext">true to attempt to marshal the continuation back to the original context captured; otherwise, false.</param>
/// <returns>Returns a <see cref="Task"/> that awaited and handled the original <paramref name="tasks"/>.</returns>
public static async Task WhenAllSafe(IEnumerable<Task> tasks, bool continueOnCapturedContext = false)
{
var whenAllTask = Task.WhenAll(tasks);

try
{
await whenAllTask.ConfigureAwait(continueOnCapturedContext);
}
catch
{
if (whenAllTask.Exception is null)
throw;

throw whenAllTask.Exception;
}
}

/// <summary>
/// Runs a <see cref="ValueTask"/> and guarantees all exceptions are caught and handled even when the <see cref="ValueTask"/> is not directly awaited.
/// </summary>
/// <param name="task">The <see cref="ValueTask"/> who's exceptions will be handled.</param>
/// <param name="continueOnCapturedContext">true to attempt to marshal the continuation back to the original context captured; otherwise, false.</param>
public static async void HandleTask(this ValueTask task, bool continueOnCapturedContext = false)
{
try
{
await task.ConfigureAwait(continueOnCapturedContext);
}
catch (Exception ex)
{
ProgramConstants.HandleException(ex);
}
}
}
3 changes: 2 additions & 1 deletion ClientCore/INIProcessing/PreprocessorBackgroundTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.IO;
using System.Threading.Tasks;
using System.Collections.Generic;
using ClientCore.Extensions;

namespace ClientCore.INIProcessing
{
Expand Down Expand Up @@ -33,7 +34,7 @@ public static PreprocessorBackgroundTask Instance

public void Run()
{
task = Task.Factory.StartNew(CheckFiles);
task = Task.Run(CheckFiles).HandleTask();
}

private static void CheckFiles()
Expand Down
2 changes: 1 addition & 1 deletion ClientCore/ProfanityFilter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ private string ToRegexPattern(string wildcardSearch)
regexPattern = regexPattern.Replace(@"\?", ".");
if (regexPattern.StartsWith(".*?"))
{
regexPattern = regexPattern.Substring(3);
regexPattern = regexPattern[3..];
regexPattern = @"(^\b)*?" + regexPattern;
}
regexPattern = @"\b" + regexPattern + @"\b";
Expand Down
Loading
Loading