diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 870f972..c2dc1ce 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -13,12 +13,12 @@ name: "CodeQL"
on:
push:
- branches: [ master ]
+ branches: [ "main" ]
pull_request:
# The branches below must be a subset of the branches above
- branches: [ master ]
+ branches: [ "main" ]
schedule:
- - cron: '44 20 * * 2'
+ - cron: '40 7 * * 5'
jobs:
analyze:
@@ -33,39 +33,44 @@ jobs:
fail-fast: false
matrix:
language: [ 'csharp' ]
- # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
- # Learn more:
- # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
+ # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
+ # Use only 'java' to analyze code written in Java, Kotlin or both
+ # Use only 'javascript' to analyze code written in JavaScript, TypeScript or both
+ # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
steps:
- name: Checkout repository
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
- uses: github/codeql-action/init@v1
+ uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
- # queries: ./path/to/local/query, your-org/your-repo/queries@main
- # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
+ # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
+ # queries: security-extended,security-and-quality
+
+
+ # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
- uses: github/codeql-action/autobuild@v1
+ uses: github/codeql-action/autobuild@v2
# ℹ️ Command-line programs to run using the OS shell.
- # 📚 https://git.io/JvXDl
+ # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
- # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
- # and modify them (or add more) to build your code if your project
- # uses a compiled language
+ # If the Autobuild fails above, remove it and uncomment the following three lines.
+ # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
- #- run: |
- # make bootstrap
- # make release
+ # - run: |
+ # echo "Run, Build Application using script"
+ # ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@v1
+ uses: github/codeql-action/analyze@v2
+ with:
+ category: "/language:${{matrix.language}}"
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 61d4882..3e07afb 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -1,6 +1,13 @@
name: MultiAdmin Build
-on: [push, pull_request]
+on:
+ push:
+ branches:
+ - main
+ - develop
+ pull_request:
+ workflow_dispatch:
+ create:
jobs:
build:
@@ -8,26 +15,32 @@ jobs:
runs-on: ${{matrix.os}}
strategy:
matrix:
- os: [ubuntu-18.04, windows-latest]
- framework: ['6.0']
+ os: [ubuntu-20.04, windows-latest]
+ framework: ['7.0']
include:
- - os: ubuntu-18.04
+ - os: ubuntu-20.04
target: linux-x64
- os: windows-latest
target: win-x64
timeout-minutes: 30
steps:
- - uses: actions/checkout@v2.3.4
+ - uses: actions/checkout@v3
- - if: matrix.os == 'ubuntu-18.04'
- name: Install Linux packages
- run: |
- sudo apt update
- sudo apt install -y clang zlib1g-dev libkrb5-dev libtinfo5
+ - if: matrix.os == 'ubuntu-20.04'
+ name: Set up Linux dependencies
+ uses: awalsh128/cache-apt-pkgs-action@latest
+ with:
+ packages: clang zlib1g-dev libkrb5-dev libtinfo5
+ # Increment to invalidate the cache
+ version: 1.0
+ # Enables a workaround to attempt to run pre and post install scripts
+ execute_install_scripts: true
+ # Disables uploading logs as a build artifact
+ debug: false
- name: Setup .NET
- uses: actions/setup-dotnet@v1.7.2
+ uses: actions/setup-dotnet@v3
with:
dotnet-version: ${{matrix.framework}}
@@ -41,13 +54,13 @@ jobs:
run: dotnet test
- name: Upload ${{matrix.target}} build
- uses: actions/upload-artifact@v2.2.2
+ uses: actions/upload-artifact@v3
with:
name: MultiAdmin-${{matrix.target}}-${{matrix.framework}}
path: ${{github.workspace}}/Builds/${{matrix.framework}}/${{matrix.target}}
- name: Upload ${{matrix.target}} build to bundle
- uses: actions/upload-artifact@v2.2.2
+ uses: actions/upload-artifact@v3
with:
name: MultiAdmin-all-${{matrix.framework}}
path: ${{github.workspace}}/Builds/${{matrix.framework}}
diff --git a/.gitignore b/.gitignore
index 920d1cd..154e127 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,7 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
-## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
# User-specific files
*.rsuser
@@ -23,6 +23,7 @@ mono_crash.*
[Rr]eleases/
x64/
x86/
+[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
@@ -56,11 +57,17 @@ dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
-# .NET Core
+# .NET
project.lock.json
project.fragment.lock.json
artifacts/
+# Tye
+.tye/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
# StyleCop
StyleCopReport.xml
@@ -86,6 +93,7 @@ StyleCopReport.xml
*.tmp_proj
*_wpftmp.csproj
*.log
+*.tlog
*.vspscc
*.vssscc
.builds
@@ -138,7 +146,9 @@ _TeamCity*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
-coverage*[.json, .xml, .info]
+coverage*.json
+coverage*.xml
+coverage*.info
# Visual Studio code coverage results
*.coverage
@@ -287,6 +297,17 @@ node_modules/
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
+# Visual Studio 6 auto-generated project file (contains which files were open etc.)
+*.vbp
+
+# Visual Studio 6 workspace and project file (working project files containing files to include in project)
+*.dsw
+*.dsp
+
+# Visual Studio 6 technical files
+*.ncb
+*.aps
+
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
@@ -343,6 +364,9 @@ ASALocalRun/
# Local History for Visual Studio
.localhistory/
+# Visual Studio History (VSHistory) files
+.vshistory/
+
# BeatPulse healthcheck temp database
healthchecksdb
@@ -352,6 +376,30 @@ MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
+# Fody - auto-generated XML schema
+FodyWeavers.xsd
+
+# VS Code files for those working on multiple tools
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+*.code-workspace
+
+# Local History for Visual Studio Code
+.history/
+
+# Windows Installer files from build outputs
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# JetBrains Rider
+*.sln.iml
+
##
## Visual studio for Mac
##
@@ -427,16 +475,3 @@ $RECYCLE.BIN/
# Windows shortcuts
*.lnk
-
-# JetBrains Rider
-.idea/
-*.sln.iml
-
-##
-## Visual Studio Code
-##
-.vscode/*
-!.vscode/settings.json
-!.vscode/tasks.json
-!.vscode/launch.json
-!.vscode/extensions.json
diff --git a/MultiAdmin.Tests/.gitignore b/MultiAdmin.Tests/.gitignore
index 920d1cd..154e127 100644
--- a/MultiAdmin.Tests/.gitignore
+++ b/MultiAdmin.Tests/.gitignore
@@ -1,7 +1,7 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
-## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
# User-specific files
*.rsuser
@@ -23,6 +23,7 @@ mono_crash.*
[Rr]eleases/
x64/
x86/
+[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
@@ -56,11 +57,17 @@ dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
-# .NET Core
+# .NET
project.lock.json
project.fragment.lock.json
artifacts/
+# Tye
+.tye/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
# StyleCop
StyleCopReport.xml
@@ -86,6 +93,7 @@ StyleCopReport.xml
*.tmp_proj
*_wpftmp.csproj
*.log
+*.tlog
*.vspscc
*.vssscc
.builds
@@ -138,7 +146,9 @@ _TeamCity*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
-coverage*[.json, .xml, .info]
+coverage*.json
+coverage*.xml
+coverage*.info
# Visual Studio code coverage results
*.coverage
@@ -287,6 +297,17 @@ node_modules/
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
+# Visual Studio 6 auto-generated project file (contains which files were open etc.)
+*.vbp
+
+# Visual Studio 6 workspace and project file (working project files containing files to include in project)
+*.dsw
+*.dsp
+
+# Visual Studio 6 technical files
+*.ncb
+*.aps
+
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
@@ -343,6 +364,9 @@ ASALocalRun/
# Local History for Visual Studio
.localhistory/
+# Visual Studio History (VSHistory) files
+.vshistory/
+
# BeatPulse healthcheck temp database
healthchecksdb
@@ -352,6 +376,30 @@ MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
+# Fody - auto-generated XML schema
+FodyWeavers.xsd
+
+# VS Code files for those working on multiple tools
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+*.code-workspace
+
+# Local History for Visual Studio Code
+.history/
+
+# Windows Installer files from build outputs
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# JetBrains Rider
+*.sln.iml
+
##
## Visual studio for Mac
##
@@ -427,16 +475,3 @@ $RECYCLE.BIN/
# Windows shortcuts
*.lnk
-
-# JetBrains Rider
-.idea/
-*.sln.iml
-
-##
-## Visual Studio Code
-##
-.vscode/*
-!.vscode/settings.json
-!.vscode/tasks.json
-!.vscode/launch.json
-!.vscode/extensions.json
diff --git a/MultiAdmin.Tests/MultiAdmin.Tests.csproj b/MultiAdmin.Tests/MultiAdmin.Tests.csproj
index e87b34b..f5f3663 100644
--- a/MultiAdmin.Tests/MultiAdmin.Tests.csproj
+++ b/MultiAdmin.Tests/MultiAdmin.Tests.csproj
@@ -1,10 +1,11 @@
- net6.0
- 8
+ net7.0
+ 11
false
MultiAdmin.Tests
-
+ enable
+
false
false
false
@@ -15,18 +16,18 @@
-
+
-
+
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
\ No newline at end of file
diff --git a/MultiAdmin.Tests/ServerIO/ShiftingListTests.cs b/MultiAdmin.Tests/ServerIO/ShiftingListTests.cs
index de287cb..8b00360 100644
--- a/MultiAdmin.Tests/ServerIO/ShiftingListTests.cs
+++ b/MultiAdmin.Tests/ServerIO/ShiftingListTests.cs
@@ -10,7 +10,7 @@ public class ShiftingListTests
public void ShiftingListTest()
{
const int maxCount = 2;
- ShiftingList shiftingList = new ShiftingList(maxCount);
+ ShiftingList shiftingList = new(maxCount);
Assert.Equal(maxCount, shiftingList.MaxCount);
}
@@ -20,7 +20,7 @@ public void AddTest()
{
const int maxCount = 2;
const int entriesToAdd = 6;
- ShiftingList shiftingList = new ShiftingList(maxCount);
+ ShiftingList shiftingList = new(maxCount);
for (int i = 0; i < entriesToAdd; i++)
{
@@ -40,7 +40,7 @@ public void RemoveFromEndTest()
{
const int maxCount = 6;
const int entriesToRemove = 2;
- ShiftingList shiftingList = new ShiftingList(maxCount);
+ ShiftingList shiftingList = new(maxCount);
for (int i = 0; i < maxCount; i++)
{
@@ -65,7 +65,7 @@ public void ReplaceTest()
{
const int maxCount = 6;
const int indexToReplace = 2;
- ShiftingList shiftingList = new ShiftingList(maxCount);
+ ShiftingList shiftingList = new(maxCount);
for (int i = 0; i < maxCount; i++)
{
diff --git a/MultiAdmin.Tests/ServerIO/StringSectionsTests.cs b/MultiAdmin.Tests/ServerIO/StringSectionsTests.cs
index dee6d8c..ab4e08c 100644
--- a/MultiAdmin.Tests/ServerIO/StringSectionsTests.cs
+++ b/MultiAdmin.Tests/ServerIO/StringSectionsTests.cs
@@ -16,10 +16,10 @@ public StringSectionsTests(ITestOutputHelper output)
}
[Theory]
- [InlineData("test string", new[] {"te", "st", " s", "tr", "in", "g"}, 2)]
- [InlineData("test string", new[] {"tes..", ".t ..", ".st..", ".ring"}, 5, ".", "..")]
+ [InlineData("test string", new[] { "te", "st", " s", "tr", "in", "g" }, 2)]
+ [InlineData("test string", new[] { "tes..", ".t ..", ".st..", ".ring" }, 5, ".", "..")]
public void FromStringTest(string testString, string[] expectedSections, int sectionLength,
- string leftIndictator = null, string rightIndictator = null)
+ string? leftIndictator = null, string? rightIndictator = null)
{
StringSections sections = StringSections.FromString(testString, sectionLength,
leftIndictator != null ? new ColoredMessage(leftIndictator) : null,
@@ -43,8 +43,8 @@ public void FromStringTest(string testString, string[] expectedSections, int sec
[Theory]
// No further characters can be output because of the prefix and suffix
[InlineData("test string", 2, ".", ".")]
- public void FromStringThrowsTest(string testString, int sectionLength, string leftIndictator = null,
- string rightIndictator = null)
+ public void FromStringThrowsTest(string testString, int sectionLength, string? leftIndictator = null,
+ string? rightIndictator = null)
{
Assert.Throws(() =>
{
diff --git a/MultiAdmin.Tests/Utility/StringExtensionsTests.cs b/MultiAdmin.Tests/Utility/StringExtensionsTests.cs
index 52b622e..1a68c29 100644
--- a/MultiAdmin.Tests/Utility/StringExtensionsTests.cs
+++ b/MultiAdmin.Tests/Utility/StringExtensionsTests.cs
@@ -14,7 +14,7 @@ public class StringExtensionsTests
[InlineData("test", "es", 1, 2)]
[InlineData(null, null, 0)]
[InlineData(null, null, 0, 1)]
- public void EqualsTest(string main, string section, int startIndex, int count = -1)
+ public void EqualsTest(string? main, string? section, int startIndex, int count = -1)
{
Assert.True(count < 0 ? main.Equals(section, startIndex) : main.Equals(section, startIndex, count));
}
@@ -27,7 +27,7 @@ public void EqualsTest(string main, string section, int startIndex, int count =
[InlineData(null, "test", 0)]
[InlineData("test", null, 0, 1)]
[InlineData(null, "test", 0, 1)]
- public void NotEqualsTest(string main, string section, int startIndex, int count = -1)
+ public void NotEqualsTest(string? main, string? section, int startIndex, int count = -1)
{
Assert.False(count < 0 ? main.Equals(section, startIndex) : main.Equals(section, startIndex, count));
}
@@ -37,7 +37,7 @@ public void NotEqualsTest(string main, string section, int startIndex, int count
[InlineData(typeof(ArgumentOutOfRangeException), "test", "st", 3)]
[InlineData(typeof(ArgumentOutOfRangeException), "test", "te", -1)]
[InlineData(typeof(ArgumentOutOfRangeException), "test", "es", 4)]
- public void EqualsThrowsTest(Type expected, string main, string section, int startIndex, int count = -1)
+ public void EqualsThrowsTest(Type expected, string? main, string? section, int startIndex, int count = -1)
{
Assert.Throws(expected, () =>
{
diff --git a/MultiAdmin.sln b/MultiAdmin.sln
index 692e8c1..294569f 100644
--- a/MultiAdmin.sln
+++ b/MultiAdmin.sln
@@ -1,5 +1,4 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
+Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26124.0
MinimumVisualStudioVersion = 15.0.26124.0
@@ -45,4 +44,4 @@ Global
{314971BB-616B-4FAE-B375-5A4A670D8626}.Release|x86.ActiveCfg = Release|Any CPU
{314971BB-616B-4FAE-B375-5A4A670D8626}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
-EndGlobal
+EndGlobal
\ No newline at end of file
diff --git a/MultiAdmin/.gitignore b/MultiAdmin/.gitignore
index 920d1cd..154e127 100644
--- a/MultiAdmin/.gitignore
+++ b/MultiAdmin/.gitignore
@@ -1,7 +1,7 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
-## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
# User-specific files
*.rsuser
@@ -23,6 +23,7 @@ mono_crash.*
[Rr]eleases/
x64/
x86/
+[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
@@ -56,11 +57,17 @@ dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
-# .NET Core
+# .NET
project.lock.json
project.fragment.lock.json
artifacts/
+# Tye
+.tye/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
# StyleCop
StyleCopReport.xml
@@ -86,6 +93,7 @@ StyleCopReport.xml
*.tmp_proj
*_wpftmp.csproj
*.log
+*.tlog
*.vspscc
*.vssscc
.builds
@@ -138,7 +146,9 @@ _TeamCity*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
-coverage*[.json, .xml, .info]
+coverage*.json
+coverage*.xml
+coverage*.info
# Visual Studio code coverage results
*.coverage
@@ -287,6 +297,17 @@ node_modules/
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
+# Visual Studio 6 auto-generated project file (contains which files were open etc.)
+*.vbp
+
+# Visual Studio 6 workspace and project file (working project files containing files to include in project)
+*.dsw
+*.dsp
+
+# Visual Studio 6 technical files
+*.ncb
+*.aps
+
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
@@ -343,6 +364,9 @@ ASALocalRun/
# Local History for Visual Studio
.localhistory/
+# Visual Studio History (VSHistory) files
+.vshistory/
+
# BeatPulse healthcheck temp database
healthchecksdb
@@ -352,6 +376,30 @@ MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
+# Fody - auto-generated XML schema
+FodyWeavers.xsd
+
+# VS Code files for those working on multiple tools
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+*.code-workspace
+
+# Local History for Visual Studio Code
+.history/
+
+# Windows Installer files from build outputs
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# JetBrains Rider
+*.sln.iml
+
##
## Visual studio for Mac
##
@@ -427,16 +475,3 @@ $RECYCLE.BIN/
# Windows shortcuts
*.lnk
-
-# JetBrains Rider
-.idea/
-*.sln.iml
-
-##
-## Visual Studio Code
-##
-.vscode/*
-!.vscode/settings.json
-!.vscode/tasks.json
-!.vscode/launch.json
-!.vscode/extensions.json
diff --git a/MultiAdmin/Config/Config.cs b/MultiAdmin/Config/Config.cs
index 133de2e..c118dd9 100644
--- a/MultiAdmin/Config/Config.cs
+++ b/MultiAdmin/Config/Config.cs
@@ -10,10 +10,11 @@ namespace MultiAdmin.Config
{
public class Config
{
- public string[] rawData = { };
+ public string[] rawData = Array.Empty();
public Config(string path)
{
+ internalConfigPath = path;
ReadConfigFile(path);
}
@@ -26,7 +27,7 @@ private set
{
try
{
- internalConfigPath = Utils.GetFullPathSafe(value);
+ internalConfigPath = Utils.GetFullPathSafe(value) ?? value;
}
catch (Exception e)
{
@@ -38,13 +39,11 @@ private set
public void ReadConfigFile(string configPath)
{
- if (string.IsNullOrEmpty(configPath)) return;
-
ConfigPath = configPath;
try
{
- rawData = File.Exists(ConfigPath) ? File.ReadAllLines(ConfigPath, Encoding.UTF8) : new string[] { };
+ rawData = File.Exists(ConfigPath) ? File.ReadAllLines(ConfigPath, Encoding.UTF8) : Array.Empty();
}
catch (Exception e)
{
@@ -52,7 +51,7 @@ public void ReadConfigFile(string configPath)
new ColoredMessage[]
{
- new ColoredMessage($"Error while reading config (Path = {ConfigPath ?? "Null"}):",
+ new ColoredMessage($"Error while reading config (Path = {ConfigPath}):",
ConsoleColor.Red),
new ColoredMessage(e.ToString(), ConsoleColor.Red)
}.WriteLines();
@@ -67,7 +66,7 @@ public void ReadConfigFile()
public bool Contains(string key)
{
return rawData != null &&
- rawData.Any(entry => entry.StartsWith($"{key}:", StringComparison.CurrentCultureIgnoreCase));
+ rawData.Any(entry => entry.StartsWith($"{key}:", StringComparison.CurrentCultureIgnoreCase));
}
private static string CleanValue(string value, bool removeQuotes = true)
@@ -79,7 +78,7 @@ private static string CleanValue(string value, bool removeQuotes = true)
try
{
if (removeQuotes && newValue.StartsWith("\"") && newValue.EndsWith("\""))
- return newValue.Substring(1, newValue.Length - 2);
+ return newValue[1..^1];
}
catch (Exception e)
{
@@ -89,7 +88,7 @@ private static string CleanValue(string value, bool removeQuotes = true)
return newValue;
}
- public string GetString(string key, string def = null, bool removeQuotes = true)
+ public string? GetString(string key, string? def = null, bool removeQuotes = true)
{
try
{
@@ -99,7 +98,7 @@ public string GetString(string key, string def = null, bool removeQuotes = true)
try
{
- return CleanValue(line.Substring(key.Length + 1), removeQuotes);
+ return CleanValue(line[(key.Length + 1)..], removeQuotes);
}
catch (Exception e)
{
@@ -115,11 +114,11 @@ public string GetString(string key, string def = null, bool removeQuotes = true)
return def;
}
- public string[] GetStringArray(string key, string[] def = null)
+ public string[]? GetStringArray(string key, string[]? def = null)
{
try
{
- string value = GetString(key, removeQuotes: false);
+ string? value = GetString(key, removeQuotes: false);
if (!string.IsNullOrEmpty(value))
{
@@ -145,7 +144,7 @@ public int GetInt(string key, int def = 0)
{
try
{
- string value = GetString(key);
+ string? value = GetString(key);
if (!string.IsNullOrEmpty(value) && int.TryParse(value, out int parseValue))
return parseValue;
@@ -162,7 +161,7 @@ public uint GetUInt(string key, uint def = 0)
{
try
{
- string value = GetString(key);
+ string? value = GetString(key);
if (!string.IsNullOrEmpty(value) && uint.TryParse(value, out uint parseValue))
return parseValue;
@@ -179,7 +178,7 @@ public float GetFloat(string key, float def = 0)
{
try
{
- string value = GetString(key);
+ string? value = GetString(key);
if (!string.IsNullOrEmpty(value) && float.TryParse(value, out float parsedValue))
return parsedValue;
@@ -196,7 +195,7 @@ public double GetDouble(string key, double def = 0)
{
try
{
- string value = GetString(key);
+ string? value = GetString(key);
if (!string.IsNullOrEmpty(value) && double.TryParse(value, out double parsedValue))
return parsedValue;
@@ -213,7 +212,7 @@ public decimal GetDecimal(string key, decimal def = 0)
{
try
{
- string value = GetString(key);
+ string? value = GetString(key);
if (!string.IsNullOrEmpty(value) && decimal.TryParse(value, out decimal parsedValue))
return parsedValue;
@@ -230,7 +229,7 @@ public bool GetBool(string key, bool def = false)
{
try
{
- string value = GetString(key);
+ string? value = GetString(key);
if (!string.IsNullOrEmpty(value) && bool.TryParse(value, out bool parsedValue))
return parsedValue;
@@ -247,7 +246,7 @@ public InputHandler.ConsoleInputSystem GetConsoleInputSystem(string key, InputHa
{
try
{
- string value = GetString(key);
+ string? value = GetString(key);
if (!string.IsNullOrEmpty(value) && Enum.TryParse(value, out var consoleInputSystem))
return consoleInputSystem;
diff --git a/MultiAdmin/Config/ConfigHandler/ConfigEntry.cs b/MultiAdmin/Config/ConfigHandler/ConfigEntry.cs
index 70e170a..6411a6b 100644
--- a/MultiAdmin/Config/ConfigHandler/ConfigEntry.cs
+++ b/MultiAdmin/Config/ConfigHandler/ConfigEntry.cs
@@ -20,12 +20,12 @@ public abstract class ConfigEntry
///
/// The value of the .
///
- public abstract object ObjectValue { get; set; }
+ public abstract object? ObjectValue { get; set; }
///
/// The default value of the .
///
- public abstract object ObjectDefault { get; set; }
+ public abstract object? ObjectDefault { get; set; }
///
/// Whether to inherit this config value from the 's parent s if they support value inheritance.
@@ -35,17 +35,17 @@ public abstract class ConfigEntry
///
/// The name of the .
///
- public string Name { get; }
+ public string? Name { get; }
///
/// The description of the .
///
- public string Description { get; }
+ public string? Description { get; }
///
/// Creates a basic with no values and indication for whether to inherit the value.
///
- public ConfigEntry(string key, bool inherit = true, string name = null, string description = null)
+ public ConfigEntry(string key, bool inherit = true, string? name = null, string? description = null)
{
Key = key;
@@ -58,7 +58,7 @@ public ConfigEntry(string key, bool inherit = true, string name = null, string d
///
/// Creates a basic with no values.
///
- public ConfigEntry(string key, string name = null, string description = null) : this(key, true, name,
+ public ConfigEntry(string key, string? name = null, string? description = null) : this(key, true, name,
description)
{
}
@@ -82,25 +82,26 @@ public class ConfigEntry : ConfigEntry
///
public T Default { get; set; }
- public override object ObjectValue
+ public override object? ObjectValue
{
get => Value;
- set => Value = (T)value;
+ set => Value = (T)value!;
}
- public override object ObjectDefault
+ public override object? ObjectDefault
{
get => Default;
- set => Default = (T)value;
+ set => Default = (T)value!;
}
///
///
/// Creates a with the provided type, default value, and indication for whether to inherit the value.
///
- public ConfigEntry(string key, T defaultValue = default, bool inherit = true, string name = null,
- string description = null) : base(key, inherit, name, description)
+ public ConfigEntry(string key, T defaultValue, bool inherit = true, string? name = null,
+ string? description = null) : base(key, inherit, name, description)
{
+ Value = defaultValue;
Default = defaultValue;
}
@@ -108,7 +109,7 @@ public ConfigEntry(string key, T defaultValue = default, bool inherit = true, st
///
/// Creates a with the provided type and default value.
///
- public ConfigEntry(string key, T defaultValue = default, string name = null, string description = null) : this(
+ public ConfigEntry(string key, T defaultValue, string? name = null, string? description = null) : this(
key, defaultValue, true, name, description)
{
}
diff --git a/MultiAdmin/Config/ConfigHandler/ConfigRegister.cs b/MultiAdmin/Config/ConfigHandler/ConfigRegister.cs
index 37cfc70..81311c1 100644
--- a/MultiAdmin/Config/ConfigHandler/ConfigRegister.cs
+++ b/MultiAdmin/Config/ConfigHandler/ConfigRegister.cs
@@ -10,7 +10,7 @@ public abstract class ConfigRegister
///
/// A list of registered s.
///
- protected readonly List registeredConfigs = new List();
+ protected readonly List registeredConfigs = new();
///
/// Returns an array of registered s.
@@ -24,7 +24,7 @@ public ConfigEntry[] GetRegisteredConfigs()
/// Returns the first with a key matching .
///
/// The key of the to retrieve.
- public ConfigEntry GetRegisteredConfig(string key)
+ public ConfigEntry? GetRegisteredConfig(string key)
{
if (string.IsNullOrEmpty(key))
return null;
@@ -47,7 +47,7 @@ public ConfigEntry GetRegisteredConfig(string key)
/// Whether to update the value of the config after registration.
public void RegisterConfig(ConfigEntry configEntry, bool updateValue = true)
{
- if (configEntry == null || string.IsNullOrEmpty(configEntry.Key))
+ if (string.IsNullOrEmpty(configEntry.Key))
return;
registeredConfigs.Add(configEntry);
@@ -63,9 +63,6 @@ public void RegisterConfig(ConfigEntry configEntry, bool updateValue = true)
/// Whether to update the value of the config after registration.
public void RegisterConfigs(ConfigEntry[] configEntries, bool updateValue = true)
{
- if (configEntries == null)
- return;
-
foreach (ConfigEntry configEntry in configEntries)
{
RegisterConfig(configEntry, updateValue);
@@ -78,7 +75,7 @@ public void RegisterConfigs(ConfigEntry[] configEntries, bool updateValue = true
/// The to be un-registered.
public void UnRegisterConfig(ConfigEntry configEntry)
{
- if (configEntry == null || string.IsNullOrEmpty(configEntry.Key))
+ if (string.IsNullOrEmpty(configEntry.Key))
return;
registeredConfigs.Remove(configEntry);
@@ -90,7 +87,9 @@ public void UnRegisterConfig(ConfigEntry configEntry)
/// The key of the to be un-registered.
public void UnRegisterConfig(string key)
{
- UnRegisterConfig(GetRegisteredConfig(key));
+ ConfigEntry? entry = GetRegisteredConfig(key);
+ if (entry != null)
+ UnRegisterConfig(entry);
}
///
@@ -99,9 +98,6 @@ public void UnRegisterConfig(string key)
/// The s to be un-registered.
public void UnRegisterConfigs(params ConfigEntry[] configEntries)
{
- if (configEntries == null)
- return;
-
foreach (ConfigEntry configEntry in configEntries)
{
UnRegisterConfig(configEntry);
@@ -114,9 +110,6 @@ public void UnRegisterConfigs(params ConfigEntry[] configEntries)
/// The keys of the s to be un-registered.
public void UnRegisterConfigs(params string[] keys)
{
- if (keys == null)
- return;
-
foreach (string key in keys)
{
UnRegisterConfig(key);
@@ -146,9 +139,6 @@ public void UnRegisterConfigs()
/// The s to be assigned values.
public void UpdateConfigValues(params ConfigEntry[] configEntries)
{
- if (configEntries == null)
- return;
-
foreach (ConfigEntry configEntry in configEntries)
{
UpdateConfigValue(configEntry);
diff --git a/MultiAdmin/Config/ConfigHandler/InheritableConfigRegister.cs b/MultiAdmin/Config/ConfigHandler/InheritableConfigRegister.cs
index ad6d52e..e08ecbd 100644
--- a/MultiAdmin/Config/ConfigHandler/InheritableConfigRegister.cs
+++ b/MultiAdmin/Config/ConfigHandler/InheritableConfigRegister.cs
@@ -11,7 +11,7 @@ public abstract class InheritableConfigRegister : ConfigRegister
/// Creates an with the parent to inherit unset config values from.
///
/// The to inherit unset config values from.
- protected InheritableConfigRegister(ConfigRegister parentConfigRegister = null)
+ protected InheritableConfigRegister(ConfigRegister? parentConfigRegister = null)
{
ParentConfigRegister = parentConfigRegister;
}
@@ -19,7 +19,7 @@ protected InheritableConfigRegister(ConfigRegister parentConfigRegister = null)
///
/// The parent to inherit from.
///
- public ConfigRegister ParentConfigRegister { get; protected set; }
+ public ConfigRegister? ParentConfigRegister { get; protected set; }
///
/// Returns whether should be inherited from the parent .
@@ -34,17 +34,17 @@ protected InheritableConfigRegister(ConfigRegister parentConfigRegister = null)
public abstract void UpdateConfigValueInheritable(ConfigEntry configEntry);
///
- /// Updates the value of from this if the is null or if returns true.
+ /// Updates the value of from this if the is null or if returns false.
///
/// The to be assigned a value.
public override void UpdateConfigValue(ConfigEntry configEntry)
{
if (configEntry != null && configEntry.Inherit && ParentConfigRegister != null &&
- ShouldInheritConfigEntry(configEntry))
+ ShouldInheritConfigEntry(configEntry))
{
ParentConfigRegister.UpdateConfigValue(configEntry);
}
- else
+ else if (configEntry != null)
{
UpdateConfigValueInheritable(configEntry);
}
@@ -56,15 +56,15 @@ public override void UpdateConfigValue(ConfigEntry configEntry)
/// Whether to order the returned array from highest in the hierarchy to the lowest.
public ConfigRegister[] GetConfigRegisterHierarchy(bool highestToLowest = true)
{
- List configRegisterHierarchy = new List();
+ List configRegisterHierarchy = new();
ConfigRegister configRegister = this;
- while (configRegister != null && !configRegisterHierarchy.Contains(configRegister))
+ while (!configRegisterHierarchy.Contains(configRegister))
{
configRegisterHierarchy.Add(configRegister);
// If there's another InheritableConfigRegister as a parent, then get the parent of that, otherwise, break the loop as there are no more parents
- if (configRegister is InheritableConfigRegister inheritableConfigRegister)
+ if (configRegister is InheritableConfigRegister inheritableConfigRegister && inheritableConfigRegister.ParentConfigRegister != null)
{
configRegister = inheritableConfigRegister.ParentConfigRegister;
}
diff --git a/MultiAdmin/Config/MultiAdminConfig.cs b/MultiAdmin/Config/MultiAdminConfig.cs
index 7911b7e..f3cba36 100644
--- a/MultiAdmin/Config/MultiAdminConfig.cs
+++ b/MultiAdmin/Config/MultiAdminConfig.cs
@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
-using System.Reflection;
using MultiAdmin.Config.ConfigHandler;
using MultiAdmin.ConsoleTools;
using MultiAdmin.ServerIO;
@@ -43,11 +42,11 @@ public class MultiAdminConfig : InheritableConfigRegister
"MultiAdmin Debug Logging", "Enables MultiAdmin debug logging, this logs to a separate file than any other logs");
public ConfigEntry DebugLogBlacklist { get; } =
- new ConfigEntry("multiadmin_debug_log_blacklist", new string[] {nameof(OutputHandler.HandleMessage), nameof(Utils.StringMatches), nameof(ServerSocket.MessageListener) },
+ new ConfigEntry("multiadmin_debug_log_blacklist", new string[] { nameof(OutputHandler.HandleMessage), nameof(Utils.StringMatches), nameof(ServerSocket.MessageListener) },
"MultiAdmin Debug Logging Blacklist", "Which tags to block for MultiAdmin debug logging");
public ConfigEntry DebugLogWhitelist { get; } =
- new ConfigEntry("multiadmin_debug_log_whitelist", new string[0],
+ new ConfigEntry("multiadmin_debug_log_whitelist", Array.Empty(),
"MultiAdmin Debug Logging Whitelist", "Which tags to log for MultiAdmin debug logging (Defaults to logging all if none are provided)");
public ConfigEntry UseNewInputSystem { get; } =
@@ -71,23 +70,23 @@ public class MultiAdminConfig : InheritableConfigRegister
"Copy from Folder on Reload", "The location of a folder to copy files from into the folder defined by `config_location` whenever the configuration file is reloaded");
public ConfigEntry FolderCopyWhitelist { get; } =
- new ConfigEntry("folder_copy_whitelist", new string[0],
+ new ConfigEntry("folder_copy_whitelist", Array.Empty(),
"Folder Copy Whitelist", "The list of file names to copy from the folder defined by `copy_from_folder_on_reload` (accepts `*` wildcards)");
public ConfigEntry FolderCopyBlacklist { get; } =
- new ConfigEntry("folder_copy_blacklist", new string[0],
+ new ConfigEntry("folder_copy_blacklist", Array.Empty(),
"Folder Copy Blacklist", "The list of file names to not copy from the folder defined by `copy_from_folder_on_reload` (accepts `*` wildcards)");
public ConfigEntry FolderCopyRoundQueue { get; } =
- new ConfigEntry("folder_copy_round_queue", new string[0],
+ new ConfigEntry("folder_copy_round_queue", Array.Empty(),
"Folder Copy Round Queue", "The location of a folder to copy files from into the folder defined by `config_location` after each round, looping through the locations");
public ConfigEntry FolderCopyRoundQueueWhitelist { get; } =
- new ConfigEntry("folder_copy_round_queue_whitelist", new string[0],
+ new ConfigEntry("folder_copy_round_queue_whitelist", Array.Empty(),
"Folder Copy Round Queue Whitelist", "The list of file names to copy from the folders defined by `folder_copy_round_queue` (accepts `*` wildcards)");
public ConfigEntry FolderCopyRoundQueueBlacklist { get; } =
- new ConfigEntry("folder_copy_round_queue_blacklist", new string[0],
+ new ConfigEntry("folder_copy_round_queue_blacklist", Array.Empty(),
"Folder Copy Round Queue Blacklist", "The list of file names to not copy from the folders defined by `folder_copy_round_queue` (accepts `*` wildcards)");
public ConfigEntry RandomizeFolderCopyRoundQueue { get; } =
@@ -180,6 +179,11 @@ public InputHandler.ConsoleInputSystem ActualConsoleInputSystem
{
get
{
+ // If defined through execution arguments, use that as an override
+ var programInputSystem = Program.ConsoleInputSystem;
+ if (programInputSystem != null)
+ return (InputHandler.ConsoleInputSystem)programInputSystem;
+
if (UseNewInputSystem.Value)
{
switch (ConsoleInputSystem.Value)
@@ -197,19 +201,19 @@ public InputHandler.ConsoleInputSystem ActualConsoleInputSystem
}
public const string ConfigFileName = "scp_multiadmin.cfg";
- public static readonly string GlobalConfigFilePath = Utils.GetFullPathSafe(ConfigFileName);
+ public static readonly string GlobalConfigFilePath = Utils.GetFullPathSafe(ConfigFileName) ?? throw new FileNotFoundException($"Config file \"{nameof(GlobalConfigFilePath)}\" was not set", ConfigFileName);
- public static readonly MultiAdminConfig GlobalConfig = new MultiAdminConfig(GlobalConfigFilePath, null);
+ public static readonly MultiAdminConfig GlobalConfig = new(GlobalConfigFilePath, null);
- public MultiAdminConfig ParentConfig
+ public MultiAdminConfig? ParentConfig
{
get => ParentConfigRegister as MultiAdminConfig;
protected set => ParentConfigRegister = value;
}
- public Config Config { get; }
+ public Config? Config { get; }
- public MultiAdminConfig(Config config, MultiAdminConfig parentConfig, bool createConfig = true)
+ public MultiAdminConfig(Config? config, MultiAdminConfig? parentConfig, bool createConfig = true)
{
Config = config;
ParentConfig = parentConfig;
@@ -234,29 +238,62 @@ public MultiAdminConfig(Config config, MultiAdminConfig parentConfig, bool creat
#region MultiAdmin Config Register
- foreach (PropertyInfo property in GetType().GetProperties())
- {
- if (property.GetValue(this) is ConfigEntry entry)
- {
- RegisterConfig(entry);
- }
- }
+ RegisterConfig(ConfigLocation);
+ RegisterConfig(AppDataLocation);
+ RegisterConfig(DisableConfigValidation);
+ RegisterConfig(ShareNonConfigs);
+ RegisterConfig(LogLocation);
+ RegisterConfig(NoLog);
+ RegisterConfig(DebugLog);
+ RegisterConfig(DebugLogBlacklist);
+ RegisterConfig(DebugLogWhitelist);
+ RegisterConfig(UseNewInputSystem);
+ RegisterConfig(ConsoleInputSystem);
+ RegisterConfig(HideInput);
+ RegisterConfig(Port);
+ RegisterConfig(CopyFromFolderOnReload);
+ RegisterConfig(FolderCopyWhitelist);
+ RegisterConfig(FolderCopyBlacklist);
+ RegisterConfig(FolderCopyRoundQueue);
+ RegisterConfig(FolderCopyRoundQueueWhitelist);
+ RegisterConfig(FolderCopyRoundQueueBlacklist);
+ RegisterConfig(RandomizeFolderCopyRoundQueue);
+ RegisterConfig(ManualStart);
+ RegisterConfig(MaxMemory);
+ RegisterConfig(RestartLowMemory);
+ RegisterConfig(RestartLowMemoryTicks);
+ RegisterConfig(RestartLowMemoryRoundEnd);
+ RegisterConfig(RestartLowMemoryRoundEndTicks);
+ RegisterConfig(RandomInputColors);
+ RegisterConfig(RestartEveryNumRounds);
+ RegisterConfig(RestartEveryNumRoundsCounting);
+ RegisterConfig(SafeServerShutdown);
+ RegisterConfig(SafeShutdownCheckDelay);
+ RegisterConfig(SafeShutdownTimeout);
+ RegisterConfig(ServerRestartTimeout);
+ RegisterConfig(ServerStopTimeout);
+ RegisterConfig(ServerStartRetry);
+ RegisterConfig(ServerStartRetryDelay);
+ RegisterConfig(MultiAdminTickDelay);
+ RegisterConfig(ServersFolder);
+ RegisterConfig(SetTitleBar);
+ RegisterConfig(StartConfigOnFull);
#endregion
ReloadConfig();
}
- public MultiAdminConfig(Config config, bool createConfig = true) : this(config, GlobalConfig, createConfig)
+ public MultiAdminConfig(Config? config, bool createConfig = true) : this(config, GlobalConfig, createConfig)
{
}
- public MultiAdminConfig(string path, MultiAdminConfig parentConfig, bool createConfig = true) : this(
- new Config(path), parentConfig, createConfig)
+ public MultiAdminConfig(string? path, MultiAdminConfig? parentConfig, bool createConfig = true) : this(
+ path != null ? new Config(path) : null, parentConfig, createConfig)
{
}
- public MultiAdminConfig(string path, bool createConfig = true) : this(path, GlobalConfig, createConfig)
+ public MultiAdminConfig(string? path, bool createConfig = true) : this(path, GlobalConfig, createConfig)
{
}
@@ -276,65 +313,65 @@ public override void UpdateConfigValueInheritable(ConfigEntry configEntry)
switch (configEntry)
{
case ConfigEntry config:
- {
- config.Value = Config.GetString(config.Key, config.Default);
- break;
- }
+ {
+ config.Value = Config.GetString(config.Key, config.Default) ?? config.Default;
+ break;
+ }
case ConfigEntry config:
- {
- config.Value = Config.GetStringArray(config.Key, config.Default);
- break;
- }
+ {
+ config.Value = Config.GetStringArray(config.Key, config.Default) ?? config.Default;
+ break;
+ }
case ConfigEntry config:
- {
- config.Value = Config.GetInt(config.Key, config.Default);
- break;
- }
+ {
+ config.Value = Config.GetInt(config.Key, config.Default);
+ break;
+ }
case ConfigEntry config:
- {
- config.Value = Config.GetUInt(config.Key, config.Default);
- break;
- }
+ {
+ config.Value = Config.GetUInt(config.Key, config.Default);
+ break;
+ }
case ConfigEntry config:
- {
- config.Value = Config.GetFloat(config.Key, config.Default);
- break;
- }
+ {
+ config.Value = Config.GetFloat(config.Key, config.Default);
+ break;
+ }
case ConfigEntry config:
- {
- config.Value = Config.GetDouble(config.Key, config.Default);
- break;
- }
+ {
+ config.Value = Config.GetDouble(config.Key, config.Default);
+ break;
+ }
case ConfigEntry config:
- {
- config.Value = Config.GetDecimal(config.Key, config.Default);
- break;
- }
+ {
+ config.Value = Config.GetDecimal(config.Key, config.Default);
+ break;
+ }
case ConfigEntry config:
- {
- config.Value = Config.GetBool(config.Key, config.Default);
- break;
- }
+ {
+ config.Value = Config.GetBool(config.Key, config.Default);
+ break;
+ }
case ConfigEntry config:
- {
- config.Value = Config.GetConsoleInputSystem(config.Key, config.Default);
- break;
- }
+ {
+ config.Value = Config.GetConsoleInputSystem(config.Key, config.Default);
+ break;
+ }
default:
- {
- throw new ArgumentException(
- $"Config type unsupported (Config: Key = \"{configEntry.Key ?? "Null"}\" Type = \"{configEntry.ValueType.FullName ?? "Null"}\" Name = \"{configEntry.Name ?? "Null"}\" Description = \"{configEntry.Description ?? "Null"}\").",
- nameof(configEntry));
- }
+ {
+ throw new ArgumentException(
+ $"Config type unsupported (Config: Key = \"{configEntry.Key ?? "Null"}\" Type = \"{configEntry.ValueType.FullName ?? "Null"}\" Name = \"{configEntry.Name ?? "Null"}\" Description = \"{configEntry.Description ?? "Null"}\").",
+ nameof(configEntry));
+ }
}
}
@@ -365,7 +402,7 @@ public bool ConfigOrGlobalConfigContains(string key)
public MultiAdminConfig[] GetConfigHierarchy(bool highestToLowest = true)
{
- List configHierarchy = new List();
+ List configHierarchy = new();
foreach (ConfigRegister configRegister in GetConfigRegisterHierarchy(highestToLowest))
{
@@ -376,12 +413,12 @@ public MultiAdminConfig[] GetConfigHierarchy(bool highestToLowest = true)
return configHierarchy.ToArray();
}
- public bool ConfigHierarchyContainsPath(string path)
+ public bool ConfigHierarchyContainsPath(string? path)
{
- string fullPath = Utils.GetFullPathSafe(path);
+ string? fullPath = Utils.GetFullPathSafe(path) ?? path;
return !string.IsNullOrEmpty(fullPath) &&
- GetConfigHierarchy().Any(config => config.Config?.ConfigPath == path);
+ GetConfigHierarchy().Any(config => config.Config?.ConfigPath == path);
}
}
}
diff --git a/MultiAdmin/ConsoleTools/ColoredConsole.cs b/MultiAdmin/ConsoleTools/ColoredConsole.cs
index a54a886..0706753 100644
--- a/MultiAdmin/ConsoleTools/ColoredConsole.cs
+++ b/MultiAdmin/ConsoleTools/ColoredConsole.cs
@@ -5,9 +5,9 @@ namespace MultiAdmin.ConsoleTools
{
public static class ColoredConsole
{
- public static readonly object WriteLock = new object();
+ public static readonly object WriteLock = new();
- public static void Write(string text, ConsoleColor? textColor = null, ConsoleColor? backgroundColor = null)
+ public static void Write(string? text, ConsoleColor? textColor = null, ConsoleColor? backgroundColor = null)
{
lock (WriteLock)
{
@@ -36,7 +36,7 @@ public static void Write(string text, ConsoleColor? textColor = null, ConsoleCol
}
}
- public static void WriteLine(string text, ConsoleColor? textColor = null, ConsoleColor? backgroundColor = null)
+ public static void WriteLine(string? text, ConsoleColor? textColor = null, ConsoleColor? backgroundColor = null)
{
lock (WriteLock)
{
@@ -46,11 +46,11 @@ public static void WriteLine(string text, ConsoleColor? textColor = null, Consol
}
}
- public static void Write(params ColoredMessage[] message)
+ public static void Write(params ColoredMessage?[] message)
{
lock (WriteLock)
{
- foreach (ColoredMessage coloredMessage in message)
+ foreach (ColoredMessage? coloredMessage in message)
{
if (coloredMessage != null)
Write(coloredMessage.text, coloredMessage.textColor, coloredMessage.backgroundColor);
@@ -58,7 +58,7 @@ public static void Write(params ColoredMessage[] message)
}
}
- public static void WriteLine(params ColoredMessage[] message)
+ public static void WriteLine(params ColoredMessage?[] message)
{
lock (WriteLock)
{
@@ -68,24 +68,24 @@ public static void WriteLine(params ColoredMessage[] message)
}
}
- public static void WriteLines(params ColoredMessage[] message)
+ public static void WriteLines(params ColoredMessage?[] message)
{
lock (WriteLock)
{
- foreach (ColoredMessage coloredMessage in message) WriteLine(coloredMessage);
+ foreach (ColoredMessage? coloredMessage in message) WriteLine(coloredMessage);
}
}
}
public class ColoredMessage : ICloneable
{
- public string text;
+ public string? text;
public ConsoleColor? textColor;
public ConsoleColor? backgroundColor;
public int Length => text?.Length ?? 0;
- public ColoredMessage(string text, ConsoleColor? textColor = null, ConsoleColor? backgroundColor = null)
+ public ColoredMessage(string? text, ConsoleColor? textColor = null, ConsoleColor? backgroundColor = null)
{
this.text = text;
this.textColor = textColor;
@@ -95,10 +95,10 @@ public ColoredMessage(string text, ConsoleColor? textColor = null, ConsoleColor?
public bool Equals(ColoredMessage other)
{
return string.Equals(text, other.text) && textColor == other.textColor &&
- backgroundColor == other.backgroundColor;
+ backgroundColor == other.backgroundColor;
}
- public override bool Equals(object obj)
+ public override bool Equals(object? obj)
{
if (ReferenceEquals(null, obj))
{
@@ -120,16 +120,10 @@ public override bool Equals(object obj)
public override int GetHashCode()
{
- unchecked
- {
- int hashCode = text != null ? text.GetHashCode() : 0;
- hashCode = (hashCode * 397) ^ textColor.GetHashCode();
- hashCode = (hashCode * 397) ^ backgroundColor.GetHashCode();
- return hashCode;
- }
+ return HashCode.Combine(text, textColor, backgroundColor);
}
- public static bool operator ==(ColoredMessage firstMessage, ColoredMessage secondMessage)
+ public static bool operator ==(ColoredMessage? firstMessage, ColoredMessage? secondMessage)
{
if (ReferenceEquals(firstMessage, secondMessage))
return true;
@@ -140,12 +134,12 @@ public override int GetHashCode()
return firstMessage.Equals(secondMessage);
}
- public static bool operator !=(ColoredMessage firstMessage, ColoredMessage secondMessage)
+ public static bool operator !=(ColoredMessage? firstMessage, ColoredMessage? secondMessage)
{
return !(firstMessage == secondMessage);
}
- public override string ToString()
+ public override string? ToString()
{
return text;
}
@@ -179,11 +173,11 @@ public void WriteLine(bool clearConsoleLine = false)
public static class ColoredMessageArrayExtensions
{
- private static string JoinTextIgnoreNull(ColoredMessage[] coloredMessages)
+ private static string JoinTextIgnoreNull(ColoredMessage?[] coloredMessages)
{
- StringBuilder builder = new StringBuilder("");
+ StringBuilder builder = new("");
- foreach (ColoredMessage coloredMessage in coloredMessages)
+ foreach (ColoredMessage? coloredMessage in coloredMessages)
{
if (coloredMessage != null)
builder.Append(coloredMessage);
@@ -192,12 +186,12 @@ private static string JoinTextIgnoreNull(ColoredMessage[] coloredMessages)
return builder.ToString();
}
- public static string GetText(this ColoredMessage[] message)
+ public static string GetText(this ColoredMessage?[] message)
{
return JoinTextIgnoreNull(message);
}
- public static void Write(this ColoredMessage[] message, bool clearConsoleLine = false)
+ public static void Write(this ColoredMessage?[] message, bool clearConsoleLine = false)
{
lock (ColoredConsole.WriteLock)
{
@@ -205,7 +199,7 @@ public static void Write(this ColoredMessage[] message, bool clearConsoleLine =
}
}
- public static void WriteLine(this ColoredMessage[] message, bool clearConsoleLine = false)
+ public static void WriteLine(this ColoredMessage?[] message, bool clearConsoleLine = false)
{
lock (ColoredConsole.WriteLock)
{
@@ -213,7 +207,7 @@ public static void WriteLine(this ColoredMessage[] message, bool clearConsoleLin
}
}
- public static void WriteLines(this ColoredMessage[] message, bool clearConsoleLine = false)
+ public static void WriteLines(this ColoredMessage?[] message, bool clearConsoleLine = false)
{
lock (ColoredConsole.WriteLock)
{
diff --git a/MultiAdmin/ConsoleTools/ConsolePositioning.cs b/MultiAdmin/ConsoleTools/ConsolePositioning.cs
index dcea3a9..3767cd1 100644
--- a/MultiAdmin/ConsoleTools/ConsolePositioning.cs
+++ b/MultiAdmin/ConsoleTools/ConsolePositioning.cs
@@ -8,7 +8,7 @@ public static class ConsolePositioning
public static BufferPoint BufferCursor
{
- get => new BufferPoint(Console.CursorLeft, Console.CursorTop);
+ get => new(Console.CursorLeft, Console.CursorTop);
set => Console.SetCursorPosition(value.x, value.y);
}
@@ -20,32 +20,32 @@ public static ConsolePoint ConsoleCursor
public static BufferPoint BufferLeft
{
- get => new BufferPoint(0, 0);
+ get => new(0, 0);
}
public static BufferPoint BufferRight
{
- get => new BufferPoint(Console.BufferWidth - 1, 0);
+ get => new(Console.BufferWidth - 1, 0);
}
public static BufferPoint BufferTop
{
- get => new BufferPoint(0, 0);
+ get => new(0, 0);
}
public static BufferPoint BufferBottom
{
- get => new BufferPoint(0, Console.BufferHeight - 1);
+ get => new(0, Console.BufferHeight - 1);
}
#endregion
}
- public struct ConsolePoint
+ public readonly struct ConsolePoint
{
public readonly int x, y;
- public BufferPoint BufferPoint => new BufferPoint(this);
+ public BufferPoint BufferPoint => new(this);
public ConsolePoint(int x, int y)
{
@@ -74,11 +74,11 @@ public void SetAsCursorY()
}
}
- public struct BufferPoint
+ public readonly struct BufferPoint
{
public readonly int x, y;
- public ConsolePoint ConsolePoint => new ConsolePoint(this);
+ public ConsolePoint ConsolePoint => new(this);
public BufferPoint(int x, int y)
{
diff --git a/MultiAdmin/ConsoleTools/ConsoleUtils.cs b/MultiAdmin/ConsoleTools/ConsoleUtils.cs
index 28d94ef..c05ff16 100644
--- a/MultiAdmin/ConsoleTools/ConsoleUtils.cs
+++ b/MultiAdmin/ConsoleTools/ConsoleUtils.cs
@@ -45,7 +45,7 @@ public static void ClearConsoleLine(int index, bool returnCursorPos = false)
}
}
- public static string ClearConsoleLine(string message)
+ public static string? ClearConsoleLine(string? message)
{
if (!string.IsNullOrEmpty(message))
ClearConsoleLine(message.Contains(Environment.NewLine) ? 0 : message.Length);
@@ -55,16 +55,16 @@ public static string ClearConsoleLine(string message)
return message;
}
- public static ColoredMessage ClearConsoleLine(ColoredMessage message)
+ public static ColoredMessage? ClearConsoleLine(ColoredMessage? message)
{
ClearConsoleLine(message?.text);
return message;
}
- public static ColoredMessage[] ClearConsoleLine(ColoredMessage[] message)
+ public static ColoredMessage?[] ClearConsoleLine(ColoredMessage?[] message)
{
ClearConsoleLine(message?.GetText());
- return message;
+ return message!;
}
#endregion
diff --git a/MultiAdmin/Features/Attributes/FeatureAttribute.cs b/MultiAdmin/Features/Attributes/FeatureAttribute.cs
deleted file mode 100644
index ce37dff..0000000
--- a/MultiAdmin/Features/Attributes/FeatureAttribute.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-using System;
-
-namespace MultiAdmin.Features.Attributes
-{
- [AttributeUsage(AttributeTargets.Class)
- ]
- public class FeatureAttribute : Attribute
- {
- }
-}
diff --git a/MultiAdmin/Features/ConfigGenerator.cs b/MultiAdmin/Features/ConfigGenerator.cs
index 0c54baa..c612d54 100644
--- a/MultiAdmin/Features/ConfigGenerator.cs
+++ b/MultiAdmin/Features/ConfigGenerator.cs
@@ -3,12 +3,10 @@
using System.IO;
using MultiAdmin.Config;
using MultiAdmin.Config.ConfigHandler;
-using MultiAdmin.Features.Attributes;
using MultiAdmin.Utility;
namespace MultiAdmin.Features
{
- [Feature]
internal class ConfigGenerator : Feature, ICommand
{
@@ -72,22 +70,22 @@ public void OnCall(string[] args)
ConfigEntry[] registeredConfigs = MultiAdminConfig.GlobalConfig.GetRegisteredConfigs();
- List lines = new List(registeredConfigs.Length);
+ List lines = new(registeredConfigs.Length);
foreach (ConfigEntry configEntry in registeredConfigs)
{
switch (configEntry)
{
case ConfigEntry config:
- {
- lines.Add($"{config.Key}: {(config.Default == null ? "" : string.Join(", ", config.Default))}");
- break;
- }
+ {
+ lines.Add($"{config.Key}: {(config.Default == null ? "" : string.Join(", ", config.Default))}");
+ break;
+ }
default:
- {
- lines.Add($"{configEntry.Key}: {configEntry.ObjectDefault ?? ""}");
- break;
- }
+ {
+ lines.Add($"{configEntry.Key}: {configEntry.ObjectDefault ?? ""}");
+ break;
+ }
}
}
diff --git a/MultiAdmin/Features/ConfigReload.cs b/MultiAdmin/Features/ConfigReload.cs
index 76c5747..d053d79 100644
--- a/MultiAdmin/Features/ConfigReload.cs
+++ b/MultiAdmin/Features/ConfigReload.cs
@@ -1,9 +1,7 @@
-using MultiAdmin.Features.Attributes;
using MultiAdmin.Utility;
namespace MultiAdmin.Features
{
- [Feature]
internal class ConfigReload : Feature, ICommand
{
public ConfigReload(Server server) : base(server)
diff --git a/MultiAdmin/Features/ExitCommand.cs b/MultiAdmin/Features/ExitCommand.cs
index e59aa12..b6eda58 100644
--- a/MultiAdmin/Features/ExitCommand.cs
+++ b/MultiAdmin/Features/ExitCommand.cs
@@ -1,8 +1,5 @@
-using MultiAdmin.Features.Attributes;
-
namespace MultiAdmin.Features
{
- [Feature]
internal class ExitCommand : Feature, ICommand
{
public ExitCommand(Server server) : base(server)
diff --git a/MultiAdmin/Features/FolderCopyRoundQueue.cs b/MultiAdmin/Features/FileCopyRoundQueue.cs
similarity index 82%
rename from MultiAdmin/Features/FolderCopyRoundQueue.cs
rename to MultiAdmin/Features/FileCopyRoundQueue.cs
index 6f91266..b78bc2e 100644
--- a/MultiAdmin/Features/FolderCopyRoundQueue.cs
+++ b/MultiAdmin/Features/FileCopyRoundQueue.cs
@@ -1,15 +1,13 @@
using System;
-using MultiAdmin.Features.Attributes;
using MultiAdmin.Utility;
namespace MultiAdmin.Features
{
- [Feature]
internal class FileCopyRoundQueue : Feature, IEventRoundEnd
{
- private string[] queue;
- private string[] whitelist;
- private string[] blacklist;
+ private string[] queue = Array.Empty();
+ private string[] whitelist = Array.Empty();
+ private string[] blacklist = Array.Empty();
private bool randomizeQueue;
private int queueIndex;
@@ -60,7 +58,7 @@ private int GetNextRandomIndex()
{
if (!HasValidQueue) return 0;
- Random random = new Random();
+ Random random = new();
int index;
do
@@ -80,9 +78,9 @@ public override void Init()
public override void OnConfigReload()
{
- queue = Server.ServerConfig.FolderCopyRoundQueue.Value;
- whitelist = Server.ServerConfig.FolderCopyRoundQueueWhitelist.Value;
- blacklist = Server.ServerConfig.FolderCopyRoundQueueBlacklist.Value;
+ queue = Server.ServerConfig.FolderCopyRoundQueue.Value ?? Array.Empty();
+ whitelist = Server.ServerConfig.FolderCopyRoundQueueWhitelist.Value ?? Array.Empty();
+ blacklist = Server.ServerConfig.FolderCopyRoundQueueBlacklist.Value ?? Array.Empty();
randomizeQueue = Server.ServerConfig.RandomizeFolderCopyRoundQueue.Value;
}
@@ -93,7 +91,7 @@ public override string GetFeatureDescription()
public override string GetFeatureName()
{
- return "Folder Copy Round Queue";
+ return "File Copy Round Queue";
}
}
}
diff --git a/MultiAdmin/Features/GithubGenerator.cs b/MultiAdmin/Features/GithubGenerator.cs
index f779cec..17d58d7 100644
--- a/MultiAdmin/Features/GithubGenerator.cs
+++ b/MultiAdmin/Features/GithubGenerator.cs
@@ -4,13 +4,11 @@
using System.Text;
using MultiAdmin.Config;
using MultiAdmin.Config.ConfigHandler;
-using MultiAdmin.Features.Attributes;
using MultiAdmin.ServerIO;
using MultiAdmin.Utility;
namespace MultiAdmin.Features
{
- [Feature]
internal class GithubGenerator : Feature, ICommand
{
public const string EmptyIndicator = "**Empty**";
@@ -74,7 +72,7 @@ public void OnCall(string[] args)
// Ignore, any proper exceptions will be presented when the file is written
}
- List lines = new List {"# MultiAdmin", "", "## Features", ""};
+ List lines = new() { "# MultiAdmin", "", "## Features", "" };
foreach (Feature feature in Server.features)
{
@@ -99,72 +97,72 @@ public void OnCall(string[] args)
foreach (ConfigEntry configEntry in MultiAdminConfig.GlobalConfig.GetRegisteredConfigs())
{
StringBuilder stringBuilder =
- new StringBuilder($"{configEntry.Key ?? EmptyIndicator}{ColumnSeparator}");
+ new($"{configEntry.Key ?? EmptyIndicator}{ColumnSeparator}");
switch (configEntry)
{
case ConfigEntry config:
- {
- stringBuilder.Append(
- $"String{ColumnSeparator}{(string.IsNullOrEmpty(config.Default) ? EmptyIndicator : config.Default)}");
- break;
- }
+ {
+ stringBuilder.Append(
+ $"String{ColumnSeparator}{(string.IsNullOrEmpty(config.Default) ? EmptyIndicator : config.Default)}");
+ break;
+ }
case ConfigEntry config:
- {
- stringBuilder.Append(
- $"String List{ColumnSeparator}{(config.Default?.IsEmpty() ?? true ? EmptyIndicator : string.Join(", ", config.Default))}");
- break;
- }
+ {
+ stringBuilder.Append(
+ $"String List{ColumnSeparator}{(config.Default?.IsEmpty() ?? true ? EmptyIndicator : string.Join(", ", config.Default))}");
+ break;
+ }
case ConfigEntry config:
- {
- stringBuilder.Append($"Integer{ColumnSeparator}{config.Default}");
- break;
- }
+ {
+ stringBuilder.Append($"Integer{ColumnSeparator}{config.Default}");
+ break;
+ }
case ConfigEntry config:
- {
- stringBuilder.Append($"Unsigned Integer{ColumnSeparator}{config.Default}");
- break;
- }
+ {
+ stringBuilder.Append($"Unsigned Integer{ColumnSeparator}{config.Default}");
+ break;
+ }
case ConfigEntry config:
- {
- stringBuilder.Append($"Float{ColumnSeparator}{config.Default}");
- break;
- }
+ {
+ stringBuilder.Append($"Float{ColumnSeparator}{config.Default}");
+ break;
+ }
case ConfigEntry config:
- {
- stringBuilder.Append($"Double{ColumnSeparator}{config.Default}");
- break;
- }
+ {
+ stringBuilder.Append($"Double{ColumnSeparator}{config.Default}");
+ break;
+ }
case ConfigEntry config:
- {
- stringBuilder.Append($"Decimal{ColumnSeparator}{config.Default}");
- break;
- }
+ {
+ stringBuilder.Append($"Decimal{ColumnSeparator}{config.Default}");
+ break;
+ }
case ConfigEntry config:
- {
- stringBuilder.Append($"Boolean{ColumnSeparator}{config.Default}");
- break;
- }
+ {
+ stringBuilder.Append($"Boolean{ColumnSeparator}{config.Default}");
+ break;
+ }
case ConfigEntry config:
- {
- stringBuilder.Append($"[ConsoleInputSystem](#ConsoleInputSystem){ColumnSeparator}{config.Default}");
- break;
- }
+ {
+ stringBuilder.Append($"[ConsoleInputSystem](#consoleinputsystem){ColumnSeparator}{config.Default}");
+ break;
+ }
default:
- {
- stringBuilder.Append(
- $"{configEntry.ValueType?.Name ?? EmptyIndicator}{ColumnSeparator}{configEntry.ObjectDefault ?? EmptyIndicator}");
- break;
- }
+ {
+ stringBuilder.Append(
+ $"{configEntry.ValueType?.Name ?? EmptyIndicator}{ColumnSeparator}{configEntry.ObjectDefault ?? EmptyIndicator}");
+ break;
+ }
}
stringBuilder.Append($"{ColumnSeparator}{configEntry.Description ?? EmptyIndicator}");
diff --git a/MultiAdmin/Features/HelpCommand.cs b/MultiAdmin/Features/HelpCommand.cs
index f2e42f1..f2200aa 100644
--- a/MultiAdmin/Features/HelpCommand.cs
+++ b/MultiAdmin/Features/HelpCommand.cs
@@ -1,15 +1,13 @@
using System;
using System.Collections.Generic;
using MultiAdmin.ConsoleTools;
-using MultiAdmin.Features.Attributes;
using MultiAdmin.Utility;
namespace MultiAdmin.Features
{
- [Feature]
public class HelpCommand : Feature, ICommand
{
- private static readonly ColoredMessage helpPrefix = new ColoredMessage("Commands from MultiAdmin:\n", ConsoleColor.Yellow);
+ private static readonly ColoredMessage helpPrefix = new("Commands from MultiAdmin:\n", ConsoleColor.Yellow);
public HelpCommand(Server server) : base(server)
{
@@ -31,7 +29,7 @@ public void OnCall(string[] args)
message[0] = helpPrefix;
- List helpOutput = new List();
+ List helpOutput = new();
foreach (KeyValuePair command in Server.commands)
{
string usage = command.Value.GetUsage();
diff --git a/MultiAdmin/Features/MemoryChecker.cs b/MultiAdmin/Features/MemoryChecker.cs
index 2280929..4ba2380 100644
--- a/MultiAdmin/Features/MemoryChecker.cs
+++ b/MultiAdmin/Features/MemoryChecker.cs
@@ -1,9 +1,7 @@
using System;
-using MultiAdmin.Features.Attributes;
namespace MultiAdmin.Features
{
- [Feature]
internal class MemoryChecker : Feature, IEventTick, IEventRoundEnd
{
private const decimal BytesInMegabyte = 1048576;
diff --git a/MultiAdmin/Features/MultiAdminInfo.cs b/MultiAdmin/Features/MultiAdminInfo.cs
index e07effb..f9bcdb9 100644
--- a/MultiAdmin/Features/MultiAdminInfo.cs
+++ b/MultiAdmin/Features/MultiAdminInfo.cs
@@ -1,9 +1,7 @@
using System;
-using MultiAdmin.Features.Attributes;
namespace MultiAdmin.Features
{
- [Feature]
internal class MultiAdminInfo : Feature, IEventServerPreStart, ICommand
{
public MultiAdminInfo(Server server) : base(server)
diff --git a/MultiAdmin/Features/NewCommand.cs b/MultiAdmin/Features/NewCommand.cs
index 2b0d355..87bfe7b 100644
--- a/MultiAdmin/Features/NewCommand.cs
+++ b/MultiAdmin/Features/NewCommand.cs
@@ -1,14 +1,12 @@
using System.Diagnostics;
-using MultiAdmin.Features.Attributes;
using MultiAdmin.Utility;
namespace MultiAdmin.Features
{
- [Feature]
internal class NewCommand : Feature, ICommand, IEventServerFull
{
- private string onFullServerId;
- private Process onFullServerInstance;
+ private string? onFullServerId;
+ private Process? onFullServerInstance;
public NewCommand(Server server) : base(server)
{
diff --git a/MultiAdmin/Features/Restart.cs b/MultiAdmin/Features/Restart.cs
index 67fad4c..cb36724 100644
--- a/MultiAdmin/Features/Restart.cs
+++ b/MultiAdmin/Features/Restart.cs
@@ -1,8 +1,5 @@
-using MultiAdmin.Features.Attributes;
-
namespace MultiAdmin.Features
{
- [Feature]
internal class Restart : Feature, ICommand
{
public Restart(Server server) : base(server)
diff --git a/MultiAdmin/Features/RestartRoundCounter.cs b/MultiAdmin/Features/RestartRoundCounter.cs
index a9517e9..f972cfa 100644
--- a/MultiAdmin/Features/RestartRoundCounter.cs
+++ b/MultiAdmin/Features/RestartRoundCounter.cs
@@ -1,8 +1,5 @@
-using MultiAdmin.Features.Attributes;
-
namespace MultiAdmin.Features
{
- [Feature]
internal class RestartRoundCounter : Feature, IEventRoundEnd
{
private int count;
diff --git a/MultiAdmin/Features/TitleBar.cs b/MultiAdmin/Features/TitleBar.cs
index 8bedad4..dfe8528 100644
--- a/MultiAdmin/Features/TitleBar.cs
+++ b/MultiAdmin/Features/TitleBar.cs
@@ -1,10 +1,8 @@
using System;
using System.Collections.Generic;
-using MultiAdmin.Features.Attributes;
namespace MultiAdmin.Features
{
- [Feature]
internal class Titlebar : Feature, IEventServerStart
{
private int ServerProcessId
@@ -53,7 +51,7 @@ private void UpdateTitlebar()
{
if (Program.Headless || !Server.ServerConfig.SetTitleBar.Value) return;
- List titleBar = new List {$"MultiAdmin {Program.MaVersion}"};
+ List titleBar = new() { $"MultiAdmin {Program.MaVersion}" };
if (!string.IsNullOrEmpty(Server.serverId))
{
diff --git a/MultiAdmin/MultiAdmin.csproj b/MultiAdmin/MultiAdmin.csproj
index 3aded0a..abafc12 100644
--- a/MultiAdmin/MultiAdmin.csproj
+++ b/MultiAdmin/MultiAdmin.csproj
@@ -1,10 +1,11 @@
Exe
- net6.0
- 8
+ net7.0
+ 11
MultiAdmin
Icon.ico
+ enable
false
false
@@ -19,6 +20,10 @@
true
+
+ true
+ true
+
false
none
@@ -31,8 +36,4 @@
-
-
-
-
-
+
\ No newline at end of file
diff --git a/MultiAdmin/NativeExitSignal/IExitSignal.cs b/MultiAdmin/NativeExitSignal/IExitSignal.cs
index 00b353f..d3acd1f 100644
--- a/MultiAdmin/NativeExitSignal/IExitSignal.cs
+++ b/MultiAdmin/NativeExitSignal/IExitSignal.cs
@@ -4,6 +4,6 @@ namespace MultiAdmin.NativeExitSignal
{
public interface IExitSignal
{
- event EventHandler Exit;
+ event EventHandler? Exit;
}
}
diff --git a/MultiAdmin/NativeExitSignal/UnixExitSignal.cs b/MultiAdmin/NativeExitSignal/UnixExitSignal.cs
index 715e9e5..ac5cbaa 100644
--- a/MultiAdmin/NativeExitSignal/UnixExitSignal.cs
+++ b/MultiAdmin/NativeExitSignal/UnixExitSignal.cs
@@ -8,7 +8,7 @@ namespace MultiAdmin.NativeExitSignal
{
public class UnixExitSignal : IExitSignal
{
- public event EventHandler Exit;
+ public event EventHandler? Exit;
private static readonly UnixSignal[] Signals = {
new UnixSignal(Signum.SIGINT), // CTRL + C pressed
diff --git a/MultiAdmin/NativeExitSignal/WinExitSignal.cs b/MultiAdmin/NativeExitSignal/WinExitSignal.cs
index a8ac2c8..8a1c7f7 100644
--- a/MultiAdmin/NativeExitSignal/WinExitSignal.cs
+++ b/MultiAdmin/NativeExitSignal/WinExitSignal.cs
@@ -5,7 +5,7 @@ namespace MultiAdmin.NativeExitSignal
{
public class WinExitSignal : IExitSignal
{
- public event EventHandler Exit;
+ public event EventHandler? Exit;
[DllImport("Kernel32")]
public static extern bool SetConsoleCtrlHandler(HandlerRoutine handler, bool add);
diff --git a/MultiAdmin/Program.cs b/MultiAdmin/Program.cs
index 38d170d..ff4d99c 100644
--- a/MultiAdmin/Program.cs
+++ b/MultiAdmin/Program.cs
@@ -3,7 +3,6 @@
using System.Diagnostics;
using System.IO;
using System.Linq;
-using System.Reflection;
using System.Threading;
using MultiAdmin.Config;
using MultiAdmin.ConsoleTools;
@@ -15,26 +14,26 @@ namespace MultiAdmin
{
public static class Program
{
- public const string MaVersion = "3.4.1.0";
+ public const string MaVersion = "3.5.0.0";
- private static readonly List InstantiatedServers = new List();
+ private static readonly List InstantiatedServers = new();
private static readonly string MaDebugLogDir =
- Utils.GetFullPathSafe(MultiAdminConfig.GlobalConfig.LogLocation.Value);
+ Utils.GetFullPathSafe(MultiAdminConfig.GlobalConfig.LogLocation.Value) ?? throw new FileNotFoundException($"Log file \"{nameof(MaDebugLogDir)}\" was not set", MultiAdminConfig.GlobalConfig.LogLocation.Value);
- private static readonly string MaDebugLogFile = !string.IsNullOrEmpty(MaDebugLogDir)
+ private static readonly string? MaDebugLogFile = !string.IsNullOrEmpty(MaDebugLogDir)
? Utils.GetFullPathSafe(Path.Combine(MaDebugLogDir, $"{Utils.DateTime}_MA_{MaVersion}_debug_log.txt"))
: null;
- private static StreamWriter debugLogStream = null;
+ private static StreamWriter? debugLogStream = null;
private static uint? portArg;
- public static readonly string[] Args = Environment.GetCommandLineArgs();
+ public static readonly string?[] Args = Environment.GetCommandLineArgs();
- private static IExitSignal exitSignalListener;
+ private static IExitSignal? exitSignalListener;
private static bool exited = false;
- private static readonly object ExitLock = new object();
+ private static readonly object ExitLock = new();
#region Server Properties
@@ -45,14 +44,14 @@ public static string[] ServerDirectories
{
get
{
- string globalServersFolder = MultiAdminConfig.GlobalConfig.ServersFolder.Value;
+ string globalServersFolder = MultiAdminConfig.GlobalConfig.ServersFolder.Value!;
return !Directory.Exists(globalServersFolder)
- ? new string[] { }
+ ? Array.Empty()
: Directory.GetDirectories(globalServersFolder);
}
}
- public static string[] ServerIds => Servers.Select(server => server.serverId).ToArray();
+ public static string[] ServerIds => Servers.Select(server => server.serverId).OfType().ToArray();
#endregion
@@ -62,14 +61,15 @@ public static string[] ServerDirectories
Servers.Where(server => !server.ServerConfig.ManualStart.Value).ToArray();
public static string[] AutoStartServerDirectories =>
- AutoStartServers.Select(autoStartServer => autoStartServer.serverDir).ToArray();
+ AutoStartServers.Select(autoStartServer => autoStartServer.serverDir).OfType().ToArray();
public static string[] AutoStartServerIds =>
- AutoStartServers.Select(autoStartServer => autoStartServer.serverId).ToArray();
+ AutoStartServers.Select(autoStartServer => autoStartServer.serverId).OfType().ToArray();
#endregion
public static bool Headless { get; private set; }
+ public static InputHandler.ConsoleInputSystem? ConsoleInputSystem { get; private set; } = null;
#region Output Printing & Logging
@@ -79,19 +79,20 @@ public static void Write(string message, ConsoleColor color = ConsoleColor.DarkY
{
if (Headless) return;
- new ColoredMessage(Utils.TimeStampMessage(message), color).WriteLine(MultiAdminConfig.GlobalConfig?.ActualConsoleInputSystem == InputHandler.ConsoleInputSystem.New);
+ new ColoredMessage(Utils.TimeStampMessage(message), color).WriteLine(MultiAdminConfig.GlobalConfig.ActualConsoleInputSystem == InputHandler.ConsoleInputSystem.New);
}
}
private static bool IsDebugLogTagAllowed(string tag)
{
- return (!MultiAdminConfig.GlobalConfig?.DebugLogBlacklist?.Value?.Contains(tag) ?? true) &&
- ((MultiAdminConfig.GlobalConfig?.DebugLogWhitelist?.Value?.IsEmpty() ?? true) ||
- MultiAdminConfig.GlobalConfig.DebugLogWhitelist.Value.Contains(tag));
+ return (!MultiAdminConfig.GlobalConfig.DebugLogBlacklist.Value.Contains(tag)) &&
+ (MultiAdminConfig.GlobalConfig.DebugLogWhitelist.Value.IsEmpty() ||
+ MultiAdminConfig.GlobalConfig.DebugLogWhitelist.Value.Contains(tag));
}
public static void LogDebugException(string tag, Exception exception)
{
+ if (MaDebugLogFile == null) return;
lock (MaDebugLogFile)
{
if (tag == null || !IsDebugLogTagAllowed(tag)) return;
@@ -102,12 +103,13 @@ public static void LogDebugException(string tag, Exception exception)
public static void LogDebug(string tag, string message)
{
+ if (MaDebugLogFile == null) return;
lock (MaDebugLogFile)
{
try
{
- if ((!MultiAdminConfig.GlobalConfig?.DebugLog?.Value ?? true) ||
- string.IsNullOrEmpty(MaDebugLogFile) || tag == null || !IsDebugLogTagAllowed(tag)) return;
+ if ((!MultiAdminConfig.GlobalConfig.DebugLog?.Value ?? true) ||
+ string.IsNullOrEmpty(MaDebugLogFile) || tag == null || !IsDebugLogTagAllowed(tag)) return;
// Assign debug log stream as needed
if (debugLogStream == null)
@@ -135,7 +137,7 @@ public static void LogDebug(string tag, string message)
#endregion
- private static void OnExit(object sender, EventArgs e)
+ private static void OnExit(object? sender, EventArgs e)
{
lock (ExitLock)
{
@@ -220,12 +222,13 @@ public static void Main()
Args[0] = null;
Headless = GetFlagFromArgs(Args, "headless", "h");
+ ConsoleInputSystem = Enum.TryParse(GetParamFromArgs(Args, "input-system", "is"), out InputHandler.ConsoleInputSystem inputSystem) ? inputSystem : null;
- string serverIdArg = GetParamFromArgs(Args, "server-id", "id");
- string configArg = GetParamFromArgs(Args, "config", "c");
- portArg = uint.TryParse(GetParamFromArgs(Args, "port", "p"), out uint port) ? (uint?)port : null;
+ string? serverIdArg = GetParamFromArgs(Args, "server-id", "id");
+ string? configArg = GetParamFromArgs(Args, "config", "c");
+ portArg = uint.TryParse(GetParamFromArgs(Args, "port", "p"), out uint port) ? port : null;
- Server server = null;
+ Server? server = null;
if (!string.IsNullOrEmpty(serverIdArg) || !string.IsNullOrEmpty(configArg))
{
@@ -294,7 +297,7 @@ public static void Main()
}
}
- public static string GetParamFromArgs(string[] args, string[] keys = null, string[] aliases = null)
+ public static string? GetParamFromArgs(string?[] args, string[]? keys = null, string[]? aliases = null)
{
bool hasKeys = !keys.IsNullOrEmpty();
bool hasAliases = !aliases.IsNullOrEmpty();
@@ -303,15 +306,15 @@ public static string GetParamFromArgs(string[] args, string[] keys = null, strin
for (int i = 0; i < args.Length - 1; i++)
{
- string lowArg = args[i]?.ToLower();
+ string? lowArg = args[i]?.ToLower();
if (string.IsNullOrEmpty(lowArg)) continue;
if (hasKeys)
{
- if (keys.Any(key => lowArg == $"--{key?.ToLower()}"))
+ if (keys?.Any(key => lowArg == $"--{key?.ToLower()}") == true)
{
- string value = args[i + 1];
+ string? value = args[i + 1];
args[i] = null;
args[i + 1] = null;
@@ -322,9 +325,9 @@ public static string GetParamFromArgs(string[] args, string[] keys = null, strin
if (hasAliases)
{
- if (aliases.Any(alias => lowArg == $"-{alias?.ToLower()}"))
+ if (aliases?.Any(alias => lowArg == $"-{alias?.ToLower()}") == true)
{
- string value = args[i + 1];
+ string? value = args[i + 1];
args[i] = null;
args[i + 1] = null;
@@ -337,7 +340,7 @@ public static string GetParamFromArgs(string[] args, string[] keys = null, strin
return null;
}
- public static bool ArgsContainsParam(string[] args, string[] keys = null, string[] aliases = null)
+ public static bool ArgsContainsParam(string?[] args, string[]? keys = null, string[]? aliases = null)
{
bool hasKeys = !keys.IsNullOrEmpty();
bool hasAliases = !aliases.IsNullOrEmpty();
@@ -346,13 +349,13 @@ public static bool ArgsContainsParam(string[] args, string[] keys = null, string
for (int i = 0; i < args.Length; i++)
{
- string lowArg = args[i]?.ToLower();
+ string? lowArg = args[i]?.ToLower();
if (string.IsNullOrEmpty(lowArg)) continue;
if (hasKeys)
{
- if (keys.Any(key => lowArg == $"--{key?.ToLower()}"))
+ if (keys?.Any(key => lowArg == $"--{key?.ToLower()}") == true)
{
args[i] = null;
return true;
@@ -361,7 +364,7 @@ public static bool ArgsContainsParam(string[] args, string[] keys = null, string
if (hasAliases)
{
- if (aliases.Any(alias => lowArg == $"-{alias?.ToLower()}"))
+ if (aliases?.Any(alias => lowArg == $"-{alias?.ToLower()}") == true)
{
args[i] = null;
return true;
@@ -372,7 +375,7 @@ public static bool ArgsContainsParam(string[] args, string[] keys = null, string
return false;
}
- public static bool GetFlagFromArgs(string[] args, string[] keys = null, string[] aliases = null)
+ public static bool GetFlagFromArgs(string?[] args, string[]? keys = null, string[]? aliases = null)
{
if (keys.IsNullOrEmpty() && aliases.IsNullOrEmpty()) return false;
@@ -381,31 +384,31 @@ public static bool GetFlagFromArgs(string[] args, string[] keys = null, string[]
: ArgsContainsParam(args, keys, aliases);
}
- public static string GetParamFromArgs(string[] args, string key = null, string alias = null)
+ public static string? GetParamFromArgs(string?[] args, string? key = null, string? alias = null)
{
- return GetParamFromArgs(args, new string[] {key}, new string[] {alias});
+ return GetParamFromArgs(args, key != null ? new string[] { key } : null, alias != null ? new string[] { alias } : null);
}
- public static bool ArgsContainsParam(string[] args, string key = null, string alias = null)
+ public static bool ArgsContainsParam(string?[] args, string? key = null, string? alias = null)
{
- return ArgsContainsParam(args, new string[] {key}, new string[] {alias});
+ return ArgsContainsParam(args, key != null ? new string[] { key } : null, alias != null ? new string[] { alias } : null);
}
- public static bool GetFlagFromArgs(string[] args, string key = null, string alias = null)
+ public static bool GetFlagFromArgs(string?[] args, string? key = null, string? alias = null)
{
- return GetFlagFromArgs(args, new string[] {key}, new string[] {alias});
+ return GetFlagFromArgs(args, key != null ? new string[] { key } : null, alias != null ? new string[] { alias } : null);
}
- public static Process StartServer(Server server)
+ public static Process? StartServer(Server server)
{
- string assemblyLocation = Assembly.GetEntryAssembly()?.Location;
+ string assemblyLocation = AppContext.BaseDirectory;
if (string.IsNullOrEmpty(assemblyLocation))
{
Write("Error while starting new server: Could not find the executable location!", ConsoleColor.Red);
}
- List args = new List(server.args);
+ List args = server.args != null ? new(server.args) : new();
if (!string.IsNullOrEmpty(server.serverId))
{
@@ -422,13 +425,13 @@ public static Process StartServer(Server server)
if (Headless)
args.Add("-h");
- ProcessStartInfo startInfo = new ProcessStartInfo(assemblyLocation, args.JoinArgs());
+ ProcessStartInfo startInfo = new(assemblyLocation, args.JoinArgs());
Write($"Launching \"{startInfo.FileName}\" with arguments \"{startInfo.Arguments}\"...");
- Process serverProcess = Process.Start(startInfo);
+ Process? serverProcess = Process.Start(startInfo);
- InstantiatedServers.Add(server);
+ if (serverProcess != null) InstantiatedServers.Add(server);
return serverProcess;
}
diff --git a/MultiAdmin/Server.cs b/MultiAdmin/Server.cs
index daa4439..34d0a2b 100644
--- a/MultiAdmin/Server.cs
+++ b/MultiAdmin/Server.cs
@@ -2,13 +2,11 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
-using System.Linq;
-using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using MultiAdmin.Config;
using MultiAdmin.ConsoleTools;
-using MultiAdmin.Features.Attributes;
+using MultiAdmin.Features;
using MultiAdmin.ServerIO;
using MultiAdmin.Utility;
@@ -16,21 +14,21 @@ namespace MultiAdmin
{
public class Server
{
- public readonly Dictionary commands = new Dictionary();
+ public readonly Dictionary commands = new();
- public readonly List features = new List();
+ public readonly List features = new();
// We want a tick only list since its the only event that happens constantly, all the rest can be in a single list
- private readonly List tick = new List();
+ private readonly List tick = new();
private readonly MultiAdminConfig serverConfig;
public MultiAdminConfig ServerConfig => serverConfig ?? MultiAdminConfig.GlobalConfig;
- public readonly string serverId;
- public readonly string configLocation;
+ public readonly string? serverId;
+ public readonly string? configLocation;
private readonly uint? port;
- public readonly string[] args;
- public readonly string serverDir;
+ public readonly string?[]? args;
+ public readonly string? serverDir;
public readonly string logDir;
public uint Port => port ?? ServerConfig.Port.Value;
@@ -40,22 +38,22 @@ public class Server
public ModFeatures supportedModFeatures = ModFeatures.None;
- public Server(string serverId = null, string configLocation = null, uint? port = null, string[] args = null)
+ public Server(string? serverId = null, string? configLocation = null, uint? port = null, string?[]? args = null)
{
this.serverId = serverId;
- serverDir = string.IsNullOrEmpty(this.serverId)
+ serverDir = string.IsNullOrEmpty(serverId)
? null
- : Utils.GetFullPathSafe(Path.Combine(MultiAdminConfig.GlobalConfig.ServersFolder.Value, this.serverId));
+ : Utils.GetFullPathSafe(Path.Combine(MultiAdminConfig.GlobalConfig.ServersFolder.Value, serverId));
this.configLocation = Utils.GetFullPathSafe(configLocation) ??
- Utils.GetFullPathSafe(MultiAdminConfig.GlobalConfig.ConfigLocation.Value) ??
- Utils.GetFullPathSafe(serverDir);
+ Utils.GetFullPathSafe(MultiAdminConfig.GlobalConfig.ConfigLocation.Value) ??
+ Utils.GetFullPathSafe(serverDir);
// Load config
serverConfig = MultiAdminConfig.GlobalConfig;
// Load config hierarchy
- string serverConfigLocation = this.configLocation;
+ string? serverConfigLocation = this.configLocation;
while (!string.IsNullOrEmpty(serverConfigLocation))
{
// Update the Server object's config location with the valid config location
@@ -81,7 +79,7 @@ public Server(string serverId = null, string configLocation = null, uint? port =
this.args = args;
logDir = Utils.GetFullPathSafe(Path.Combine(string.IsNullOrEmpty(serverDir) ? "" : serverDir,
- serverConfig.LogLocation.Value));
+ serverConfig.LogLocation.Value)) ?? throw new FileNotFoundException($"Log file \"{nameof(logDir)}\" was not set");
// Register all features
RegisterFeatures();
@@ -104,7 +102,7 @@ private set
}
public bool IsStopped => Status == ServerStatus.NotStarted || Status == ServerStatus.Stopped ||
- Status == ServerStatus.StoppedUnexpectedly;
+ Status == ServerStatus.StoppedUnexpectedly;
public bool IsRunning => !IsStopped;
public bool IsStarted => !IsStopped && !IsStarting;
@@ -112,7 +110,7 @@ private set
public bool IsStarting => Status == ServerStatus.Starting;
public bool IsStopping => Status == ServerStatus.Stopping || Status == ServerStatus.ForceStopping ||
- Status == ServerStatus.Restarting;
+ Status == ServerStatus.Restarting;
public bool IsLoading { get; set; }
@@ -131,9 +129,9 @@ public bool SetServerRequestedStatus(ServerStatus status)
#endregion
- private string startDateTime;
+ private string? startDateTime;
- public string StartDateTime
+ public string? StartDateTime
{
get => startDateTime;
@@ -160,13 +158,13 @@ private set
public bool CheckRestartTimeout =>
(DateTime.Now - initRestartTimeoutTime).Seconds > ServerConfig.ServerRestartTimeout.Value;
- public string LogDirFile { get; private set; }
- public string MaLogFile { get; private set; }
- public string ScpLogFile { get; private set; }
+ public string? LogDirFile { get; private set; }
+ public string? MaLogFile { get; private set; }
+ public string? ScpLogFile { get; private set; }
- private StreamWriter maLogStream;
+ private StreamWriter? maLogStream;
- public Process GameProcess { get; private set; }
+ public Process? GameProcess { get; private set; }
public bool IsGameProcessRunning
{
@@ -182,16 +180,16 @@ public bool IsGameProcessRunning
}
- public static readonly string DedicatedDir = Utils.GetFullPathSafe(Path.Combine("SCPSL_Data", "Dedicated"));
+ public static readonly string? DedicatedDir = Utils.GetFullPathSafe(Path.Combine("SCPSL_Data", "Dedicated"));
- public ServerSocket SessionSocket { get; private set; }
+ public ServerSocket? SessionSocket { get; private set; }
#region Server Core
private void MainLoop()
{
// Creates and starts a timer
- Stopwatch timer = new Stopwatch();
+ Stopwatch timer = new();
timer.Restart();
while (IsGameProcessRunning)
@@ -255,13 +253,13 @@ public void WriteConfigInformation()
foreach (MultiAdminConfig config in ServerConfig.GetConfigHierarchy())
{
if (!string.IsNullOrEmpty(config?.Config?.ConfigPath) &&
- MultiAdminConfig.GlobalConfigFilePath != config.Config.ConfigPath)
+ MultiAdminConfig.GlobalConfigFilePath != config.Config.ConfigPath)
Write($"Using server config \"{config.Config.ConfigPath}\"...");
}
}
}
- public string GetExecutablePath()
+ public static string GetExecutablePath()
{
string scpslExe;
@@ -297,7 +295,7 @@ public void StartServer(bool restartOnCrash = true)
// Set up logging
maLogStream?.Close();
Directory.CreateDirectory(logDir);
- maLogStream = File.AppendText(MaLogFile);
+ maLogStream = File.AppendText(MaLogFile ?? throw new FileNotFoundException($"Log file \"{nameof(MaLogFile)}\" was not set"));
#region Startup Info Printing & Logging
@@ -316,20 +314,20 @@ public void StartServer(bool restartOnCrash = true)
Write($"Executing \"{scpslExe}\"...", ConsoleColor.DarkGreen);
// Start the console socket connection to the game server
- ServerSocket consoleSocket = new ServerSocket();
+ ServerSocket consoleSocket = new();
// Start the connection before the game to find an open port for communication
consoleSocket.Connect();
SessionSocket = consoleSocket;
- List scpslArgs = new List
+ List scpslArgs = new()
{
$"-multiadmin:{Program.MaVersion}:{(int)ModFeatures.All}",
"-batchmode",
"-nographics",
"-silent-crashes",
"-nodedicateddelete",
- $"-id{Process.GetCurrentProcess().Id}",
+ $"-id{Environment.ProcessId}",
$"-console{consoleSocket.Port}",
$"-port{Port}"
};
@@ -371,7 +369,7 @@ public void StartServer(bool restartOnCrash = true)
scpslArgs.Add(configLocation);
}
- string appDataPath = Utils.GetFullPathSafe(ServerConfig.AppDataLocation.Value);
+ string? appDataPath = Utils.GetFullPathSafe(ServerConfig.AppDataLocation.Value);
if (!string.IsNullOrEmpty(appDataPath))
{
scpslArgs.Add("-appdatapath");
@@ -379,11 +377,12 @@ public void StartServer(bool restartOnCrash = true)
}
// Add custom arguments
- scpslArgs.AddRange(args);
+ if (args != null) scpslArgs.AddRange(args);
- ProcessStartInfo startInfo = new ProcessStartInfo(scpslExe, scpslArgs.JoinArgs())
+ ProcessStartInfo startInfo = new(scpslExe, scpslArgs.JoinArgs())
{
- CreateNoWindow = true, UseShellExecute = false
+ CreateNoWindow = true,
+ UseShellExecute = false
};
Write($"Starting server with the following parameters:\n{scpslExe} {startInfo.Arguments}");
@@ -397,8 +396,8 @@ public void StartServer(bool restartOnCrash = true)
ForEachHandler(eventPreStart => eventPreStart.OnServerPreStart());
// Start the input reader
- CancellationTokenSource inputHandlerCancellation = new CancellationTokenSource();
- Task inputHandler = null;
+ CancellationTokenSource inputHandlerCancellation = new();
+ Task? inputHandler = null;
if (!Program.Headless)
{
@@ -406,7 +405,7 @@ public void StartServer(bool restartOnCrash = true)
}
// Start the output reader
- OutputHandler outputHandler = new OutputHandler(this);
+ OutputHandler outputHandler = new(this);
// Assign the socket events to the OutputHandler
consoleSocket.OnReceiveMessage += outputHandler.HandleMessage;
consoleSocket.OnReceiveAction += outputHandler.HandleAction;
@@ -447,7 +446,7 @@ public void StartServer(bool restartOnCrash = true)
}
// Cleanup after exit from MainLoop
- GameProcess.Dispose();
+ GameProcess?.Dispose();
GameProcess = null;
// Stop the input handler if it's running
@@ -534,7 +533,7 @@ public void StopServer(bool killGame = false)
SetStopStatus(killGame);
if ((killGame || !SendMessage("QUIT")) && IsGameProcessRunning)
- GameProcess.Kill();
+ GameProcess?.Kill();
}
public void SetRestartStatus()
@@ -552,7 +551,7 @@ public void RestartServer(bool killGame = false)
SetRestartStatus();
if ((killGame || !SendMessage("SOFTRESTART")) && IsGameProcessRunning)
- GameProcess.Kill();
+ GameProcess?.Kill();
}
#endregion
@@ -568,57 +567,44 @@ private void RegisterFeature(Feature feature)
break;
case ICommand command:
- {
- string commandKey = command.GetCommand().ToLower().Trim();
-
- // If the command was already registered
- if (commands.ContainsKey(commandKey))
{
- string message =
- $"Warning, {nameof(MultiAdmin)} tried to register duplicate command \"{commandKey}\"";
+ string commandKey = command.GetCommand().ToLower().Trim();
- Program.LogDebug(nameof(RegisterFeature), message);
- Write(message);
- }
- else
- {
- commands.Add(commandKey, command);
- }
+ // If the command was already registered
+ if (commands.ContainsKey(commandKey))
+ {
+ string message =
+ $"Warning, {nameof(MultiAdmin)} tried to register duplicate command \"{commandKey}\"";
- break;
- }
+ Program.LogDebug(nameof(RegisterFeature), message);
+ Write(message);
+ }
+ else
+ {
+ commands.Add(commandKey, command);
+ }
+
+ break;
+ }
}
features.Add(feature);
}
- private static IEnumerable GetTypesWithAttribute(Type attribute)
- {
- foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
- {
- foreach (Type type in assembly.GetTypes())
- {
- object[] attributes = type.GetCustomAttributes(attribute, true);
- if (!attributes.IsEmpty()) yield return type;
- }
- }
- }
-
private void RegisterFeatures()
{
- Type[] assembly = GetTypesWithAttribute(typeof(FeatureAttribute)).ToArray();
- foreach (Type type in assembly)
- {
- try
- {
- object featureInstance = Activator.CreateInstance(type, this);
- if (featureInstance is Feature feature) RegisterFeature(feature);
- }
- catch (Exception e)
- {
- Program.LogDebugException(nameof(RegisterFeatures), e);
- }
- }
+ RegisterFeature(new ConfigGenerator(this));
+ RegisterFeature(new ConfigReload(this));
+ RegisterFeature(new ExitCommand(this));
+ RegisterFeature(new FileCopyRoundQueue(this));
+ RegisterFeature(new GithubGenerator(this));
+ RegisterFeature(new HelpCommand(this));
+ RegisterFeature(new MemoryChecker(this));
+ RegisterFeature(new MultiAdminInfo(this));
+ RegisterFeature(new NewCommand(this));
+ RegisterFeature(new Restart(this));
+ RegisterFeature(new RestartRoundCounter(this));
+ RegisterFeature(new Titlebar(this));
}
private void InitFeatures()
@@ -641,7 +627,7 @@ public void ForEachHandler(Action action) where T : IMAEvent
#region Console Output and Logging
- public void Write(ColoredMessage[] messages, ConsoleColor? timeStampColor = null)
+ public void Write(ColoredMessage?[] messages, ConsoleColor? timeStampColor = null)
{
lock (ColoredConsole.WriteLock)
{
@@ -651,7 +637,7 @@ public void Write(ColoredMessage[] messages, ConsoleColor? timeStampColor = null
if (Program.Headless) return;
- ColoredMessage[] timeStampedMessage = Utils.TimeStampMessage(messages, timeStampColor);
+ ColoredMessage?[] timeStampedMessage = Utils.TimeStampMessage(messages, timeStampColor);
timeStampedMessage.WriteLine(ServerConfig.ActualConsoleInputSystem == InputHandler.ConsoleInputSystem.New);
@@ -664,7 +650,7 @@ public void Write(ColoredMessage message, ConsoleColor? timeStampColor = null)
{
lock (ColoredConsole.WriteLock)
{
- Write(new ColoredMessage[] {message}, timeStampColor ?? message.textColor);
+ Write(new ColoredMessage[] { message }, timeStampColor ?? message.textColor);
}
}
@@ -681,7 +667,7 @@ public void Log(string message)
{
lock (ColoredConsole.WriteLock)
{
- if (message == null || string.IsNullOrEmpty(MaLogFile) || ServerConfig.NoLog.Value) return;
+ if (maLogStream == null || string.IsNullOrEmpty(MaLogFile) || ServerConfig.NoLog.Value) return;
try
{
@@ -712,7 +698,7 @@ public void ReloadConfig(bool copyFiles = true, bool runEvent = true)
// Handle directory copying
string copyFromDir;
if (copyFiles && !string.IsNullOrEmpty(configLocation) &&
- !string.IsNullOrEmpty(copyFromDir = ServerConfig.CopyFromFolderOnReload.Value))
+ !string.IsNullOrEmpty(copyFromDir = ServerConfig.CopyFromFolderOnReload.Value))
{
CopyFromDir(copyFromDir, ServerConfig.FolderCopyWhitelist.Value,
ServerConfig.FolderCopyBlacklist.Value);
@@ -724,7 +710,7 @@ public void ReloadConfig(bool copyFiles = true, bool runEvent = true)
feature.OnConfigReload();
}
- public bool CopyFromDir(string sourceDir, string[] fileWhitelist = null, string[] fileBlacklist = null)
+ public bool CopyFromDir(string? sourceDir, string[]? fileWhitelist = null, string[]? fileBlacklist = null)
{
if (string.IsNullOrEmpty(configLocation) || string.IsNullOrEmpty(sourceDir)) return false;
diff --git a/MultiAdmin/ServerIO/InputHandler.cs b/MultiAdmin/ServerIO/InputHandler.cs
index 32520e2..6993f23 100644
--- a/MultiAdmin/ServerIO/InputHandler.cs
+++ b/MultiAdmin/ServerIO/InputHandler.cs
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
-using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
@@ -11,13 +10,13 @@ namespace MultiAdmin.ServerIO
{
public static class InputHandler
{
- private static readonly char[] Separator = {' '};
+ private static readonly char[] Separator = { ' ' };
- public static readonly ColoredMessage BaseSection = new ColoredMessage(null, ConsoleColor.White);
+ public static readonly ColoredMessage BaseSection = new(null, ConsoleColor.White);
- public static readonly ColoredMessage InputPrefix = new ColoredMessage("> ", ConsoleColor.Yellow);
- public static readonly ColoredMessage LeftSideIndicator = new ColoredMessage("...", ConsoleColor.Yellow);
- public static readonly ColoredMessage RightSideIndicator = new ColoredMessage("...", ConsoleColor.Yellow);
+ public static readonly ColoredMessage InputPrefix = new("> ", ConsoleColor.Yellow);
+ public static readonly ColoredMessage LeftSideIndicator = new("...", ConsoleColor.Yellow);
+ public static readonly ColoredMessage RightSideIndicator = new("...", ConsoleColor.Yellow);
public static int InputPrefixLength => InputPrefix?.Length ?? 0;
@@ -42,15 +41,15 @@ public static int SectionBufferWidth
}
}
- public static string CurrentMessage { get; private set; }
- public static ColoredMessage[] CurrentInput { get; private set; } = {InputPrefix};
+ public static string? CurrentMessage { get; private set; }
+ public static ColoredMessage?[]? CurrentInput { get; private set; } = { InputPrefix };
public static int CurrentCursor { get; private set; }
public static async void Write(Server server, CancellationToken cancellationToken)
{
try
{
- ShiftingList prevMessages = new ShiftingList(25);
+ ShiftingList prevMessages = new(25);
while (server.IsRunning && !server.IsStopping)
{
@@ -59,10 +58,10 @@ public static async void Write(Server server, CancellationToken cancellationToke
break;
}
- string message;
+ string? message;
if (server.ServerConfig.ActualConsoleInputSystem == ConsoleInputSystem.New && SectionBufferWidth - TotalIndicatorLength > 0)
{
- message = await GetInputLineNew(server, cancellationToken, prevMessages);
+ message = await GetInputLineNew(server, prevMessages, cancellationToken);
}
else if (server.ServerConfig.ActualConsoleInputSystem == ConsoleInputSystem.Old)
{
@@ -78,12 +77,11 @@ public static async void Write(Server server, CancellationToken cancellationToke
server.Write($">>> {message}", ConsoleColor.DarkMagenta);
int separatorIndex = message.IndexOfAny(Separator);
- string commandName = (separatorIndex < 0 ? message : message.Substring(0, separatorIndex)).ToLower().Trim();
+ string commandName = (separatorIndex < 0 ? message : message[..separatorIndex]).ToLower().Trim();
if (commandName.IsNullOrEmpty()) continue;
bool callServer = true;
- server.commands.TryGetValue(commandName, out ICommand command);
- if (command != null)
+ if (server.commands.TryGetValue(commandName, out ICommand? command))
{
try
{
@@ -124,7 +122,7 @@ public static async Task WaitForKey(CancellationToken cancellationToken)
public static async Task GetInputLineOld(Server server, CancellationToken cancellationToken)
{
- StringBuilder message = new StringBuilder();
+ StringBuilder message = new();
while (true)
{
await WaitForKey(cancellationToken);
@@ -148,7 +146,7 @@ public static async Task GetInputLineOld(Server server, CancellationToke
}
}
- public static async Task GetInputLineNew(Server server, CancellationToken cancellationToken, ShiftingList prevMessages)
+ public static async Task GetInputLineNew(Server server, ShiftingList prevMessages, CancellationToken cancellationToken)
{
if (server.ServerConfig.RandomInputColors.Value)
RandomizeInputColors();
@@ -157,7 +155,7 @@ public static async Task GetInputLineNew(Server server, CancellationToke
string message = "";
int messageCursor = 0;
int prevMessageCursor = -1;
- StringSections curSections = null;
+ StringSections? curSections = null;
int lastSectionIndex = -1;
bool exitLoop = false;
while (!exitLoop)
@@ -354,9 +352,9 @@ public static void ResetInputParams()
CurrentCursor = 0;
}
- public static void SetCurrentInput(params ColoredMessage[] coloredMessages)
+ public static void SetCurrentInput(params ColoredMessage?[]? coloredMessages)
{
- List message = new List {InputPrefix};
+ List message = new() { InputPrefix };
if (coloredMessages != null)
message.AddRange(coloredMessages);
@@ -366,7 +364,7 @@ public static void SetCurrentInput(params ColoredMessage[] coloredMessages)
public static void SetCurrentInput(string message)
{
- ColoredMessage baseSection = BaseSection?.Clone();
+ ColoredMessage? baseSection = BaseSection?.Clone();
if (baseSection == null)
baseSection = new ColoredMessage(message);
@@ -412,7 +410,7 @@ public static void SetCursor()
SetCursor(CurrentCursor);
}
- public static void WriteInput(ColoredMessage[] message, bool clearConsoleLine = false)
+ public static void WriteInput(ColoredMessage?[]? message, bool clearConsoleLine = false)
{
lock (ColoredConsole.WriteLock)
{
@@ -444,11 +442,11 @@ public static void RandomizeInputColors()
{
try
{
- Random random = new Random();
- Array colors = Enum.GetValues(typeof(ConsoleColor));
+ Random random = new();
+ ConsoleColor[] colors = Enum.GetValues();
- ConsoleColor random1 = (ConsoleColor)colors.GetValue(random.Next(colors.Length));
- ConsoleColor random2 = (ConsoleColor)colors.GetValue(random.Next(colors.Length));
+ ConsoleColor random1 = colors[random.Next(colors.Length)];
+ ConsoleColor random2 = colors[random.Next(colors.Length)];
BaseSection.textColor = random1;
diff --git a/MultiAdmin/ServerIO/OutputHandler.cs b/MultiAdmin/ServerIO/OutputHandler.cs
index e8b9883..168c251 100644
--- a/MultiAdmin/ServerIO/OutputHandler.cs
+++ b/MultiAdmin/ServerIO/OutputHandler.cs
@@ -8,9 +8,9 @@ namespace MultiAdmin.ServerIO
public class OutputHandler
{
public static readonly Regex SmodRegex =
- new Regex(@"\[(DEBUG|INFO|WARN|ERROR)\] (\[.*?\]) (.*)", RegexOptions.Compiled | RegexOptions.Singleline);
+ new(@"\[(DEBUG|INFO|WARN|ERROR)\] (\[.*?\]) (.*)", RegexOptions.Compiled | RegexOptions.Singleline);
public static readonly char[] TrimChars = { '.', ' ', '\t', '!', '?', ',' };
- public static readonly char[] EventSplitChars = new char[] {':'};
+ public static readonly char[] EventSplitChars = new char[] { ':' };
private readonly Server server;
@@ -36,20 +36,20 @@ public OutputHandler(Server server)
this.server = server;
}
- public void HandleMessage(object source, ServerSocket.MessageEventArgs message)
+ public void HandleMessage(object? source, ServerSocket.MessageEventArgs message)
{
if (message.message == null)
return;
- ColoredMessage coloredMessage = new ColoredMessage(message.message, ConsoleColor.White);
+ ColoredMessage coloredMessage = new(message.message, ConsoleColor.White);
- if (!coloredMessage.text.IsEmpty())
+ if (!coloredMessage.text.IsNullOrEmpty())
{
// Parse the color byte
coloredMessage.textColor = (ConsoleColor)message.color;
// Smod2 loggers pretty printing
- Match match = SmodRegex.Match(coloredMessage.text);
+ Match match = SmodRegex.Match(coloredMessage.text!);
if (match.Success)
{
if (match.Groups.Count >= 3)
@@ -93,7 +93,7 @@ public void HandleMessage(object source, ServerSocket.MessageEventArgs message)
}
}
- string lowerMessage = coloredMessage.text.ToLower();
+ string lowerMessage = coloredMessage.text!.ToLower();
if (!server.supportedModFeatures.HasFlag(ModFeatures.CustomEvents))
{
switch (lowerMessage.Trim(TrimChars))
@@ -127,13 +127,13 @@ public void HandleMessage(object source, ServerSocket.MessageEventArgs message)
if (lowerMessage.StartsWith("multiadmin:"))
{
// 11 chars in "multiadmin:"
- string eventMessage = coloredMessage.text.Substring(11);
+ string eventMessage = coloredMessage.text[11..];
// Split event and event data
string[] eventSplit = eventMessage.Split(EventSplitChars, 2);
string @event = eventSplit[0].ToLower();
- string eventData = eventSplit.Length > 1 ? eventSplit[1] : null; // Handle events with no data
+ string? eventData = eventSplit.Length > 1 ? eventSplit[1] : null; // Handle events with no data
switch (@event)
{
@@ -177,7 +177,7 @@ public void HandleMessage(object source, ServerSocket.MessageEventArgs message)
server.Write(coloredMessage);
}
- public void HandleAction(object source, byte action)
+ public void HandleAction(object? source, byte action)
{
switch ((OutputCodes)action)
{
diff --git a/MultiAdmin/ServerIO/ServerSocket.cs b/MultiAdmin/ServerIO/ServerSocket.cs
index 6a176cd..25e25a5 100644
--- a/MultiAdmin/ServerIO/ServerSocket.cs
+++ b/MultiAdmin/ServerIO/ServerSocket.cs
@@ -10,30 +10,30 @@ namespace MultiAdmin.ServerIO
public class ServerSocket : IDisposable
{
private const int IntBytes = sizeof(int);
- public static readonly UTF8Encoding Encoding = new UTF8Encoding(false, true);
+ public static readonly UTF8Encoding Encoding = new(false, true);
- private readonly CancellationTokenSource disposeCancellationSource = new CancellationTokenSource();
+ private readonly CancellationTokenSource disposeCancellationSource = new();
private bool disposed = false;
private readonly TcpListener listener;
- private TcpClient client;
- private NetworkStream networkStream;
+ private TcpClient? client;
+ private NetworkStream? networkStream;
- public struct MessageEventArgs
+ public readonly struct MessageEventArgs
{
- public MessageEventArgs(string message, byte color)
+ public MessageEventArgs(string? message, byte color)
{
this.message = message;
this.color = color;
}
- public readonly string message;
+ public readonly string? message;
public readonly byte color;
}
- public event EventHandler OnReceiveMessage;
- public event EventHandler OnReceiveAction;
+ public event EventHandler? OnReceiveMessage;
+ public event EventHandler? OnReceiveAction;
public int Port => ((IPEndPoint)listener.LocalEndpoint).Port;
@@ -74,13 +74,17 @@ public void Connect()
public async void MessageListener()
{
byte[] typeBuffer = new byte[1];
+ Memory typeBufferMemory = new(typeBuffer);
+
byte[] intBuffer = new byte[IntBytes];
+ Memory intBufferMemory = new(intBuffer);
+
while (!disposed && networkStream != null)
{
try
{
int messageTypeBytesRead =
- await networkStream.ReadAsync(typeBuffer, 0, 1, disposeCancellationSource.Token);
+ await networkStream.ReadAsync(typeBufferMemory, disposeCancellationSource.Token);
// Socket has been disconnected
if (messageTypeBytesRead <= 0)
@@ -99,7 +103,7 @@ public async void MessageListener()
}
int lengthBytesRead =
- await networkStream.ReadAsync(intBuffer, 0, IntBytes, disposeCancellationSource.Token);
+ await networkStream.ReadAsync(intBufferMemory, disposeCancellationSource.Token);
// Socket has been disconnected or integer read is invalid
if (lengthBytesRead != IntBytes)
@@ -123,7 +127,7 @@ public async void MessageListener()
byte[] messageBuffer = new byte[length];
int messageBytesRead =
- await networkStream.ReadAsync(messageBuffer, 0, length, disposeCancellationSource.Token);
+ await networkStream.ReadAsync(messageBuffer.AsMemory(0, length), disposeCancellationSource.Token);
// Socket has been disconnected
if (messageBytesRead <= 0)
@@ -176,6 +180,8 @@ public void Dispose()
if (disposed)
return;
+ GC.SuppressFinalize(this);
+
disposed = true;
disposeCancellationSource.Cancel();
disposeCancellationSource.Dispose();
diff --git a/MultiAdmin/ServerIO/StringSections.cs b/MultiAdmin/ServerIO/StringSections.cs
index be27d92..49d2aa6 100644
--- a/MultiAdmin/ServerIO/StringSections.cs
+++ b/MultiAdmin/ServerIO/StringSections.cs
@@ -45,8 +45,8 @@ public StringSections(StringSection[] sections)
}
public static StringSections FromString(string fullString, int sectionLength,
- ColoredMessage leftIndicator = null, ColoredMessage rightIndicator = null,
- ColoredMessage sectionBase = null)
+ ColoredMessage? leftIndicator = null, ColoredMessage? rightIndicator = null,
+ ColoredMessage? sectionBase = null)
{
int rightIndicatorLength = rightIndicator?.Length ?? 0;
int totalIndicatorLength = (leftIndicator?.Length ?? 0) + rightIndicatorLength;
@@ -56,7 +56,7 @@ public static StringSections FromString(string fullString, int sectionLength,
$"{nameof(sectionLength)} must be greater than the total length of {nameof(leftIndicator)} and {nameof(rightIndicator)}",
nameof(sectionLength));
- List sections = new List();
+ List sections = new();
if (string.IsNullOrEmpty(fullString))
return new StringSections(sections.ToArray());
@@ -69,7 +69,7 @@ public static StringSections FromString(string fullString, int sectionLength,
int sectionStartIndex = 0;
// The text of the current section being created
- StringBuilder curSecBuilder = new StringBuilder();
+ StringBuilder curSecBuilder = new();
for (int i = 0; i < fullString.Length; i++)
{
@@ -79,9 +79,9 @@ public static StringSections FromString(string fullString, int sectionLength,
if (curSecBuilder.Length < sectionLength - totalIndicatorLength) continue;
// Decide what the left indicator text should be accounting for the leftmost section
- ColoredMessage leftIndicatorSection = sections.Count > 0 ? leftIndicator : null;
+ ColoredMessage? leftIndicatorSection = sections.Count > 0 ? leftIndicator : null;
// Decide what the right indicator text should be accounting for the rightmost section
- ColoredMessage rightIndicatorSection =
+ ColoredMessage? rightIndicatorSection =
i < fullString.Length - (1 + rightIndicatorLength) ? rightIndicator : null;
// Check the section length against the final section length
@@ -106,7 +106,7 @@ public static StringSections FromString(string fullString, int sectionLength,
if (!curSecBuilder.IsEmpty())
{
// Only decide for the left indicator, as this last section will always be the rightmost section
- ColoredMessage leftIndicatorSection = sections.Count > 0 ? leftIndicator : null;
+ ColoredMessage? leftIndicatorSection = sections.Count > 0 ? leftIndicator : null;
// Copy the section base message and replace the text
ColoredMessage section = sectionBase.Clone();
@@ -121,19 +121,19 @@ public static StringSections FromString(string fullString, int sectionLength,
}
}
- public struct StringSection
+ public readonly struct StringSection
{
public ColoredMessage Text { get; }
- public ColoredMessage LeftIndicator { get; }
- public ColoredMessage RightIndicator { get; }
+ public ColoredMessage? LeftIndicator { get; }
+ public ColoredMessage? RightIndicator { get; }
- public ColoredMessage[] Section => new ColoredMessage[] {LeftIndicator, Text, RightIndicator};
+ public ColoredMessage?[] Section => new ColoredMessage?[] { LeftIndicator, Text, RightIndicator };
public int MinIndex { get; }
public int MaxIndex { get; }
- public StringSection(ColoredMessage text, ColoredMessage leftIndicator, ColoredMessage rightIndicator,
+ public StringSection(ColoredMessage text, ColoredMessage? leftIndicator, ColoredMessage? rightIndicator,
int minIndex, int maxIndex)
{
Text = text;
diff --git a/MultiAdmin/Utility/CommandUtils.cs b/MultiAdmin/Utility/CommandUtils.cs
index be0380a..8dd2f80 100644
--- a/MultiAdmin/Utility/CommandUtils.cs
+++ b/MultiAdmin/Utility/CommandUtils.cs
@@ -62,11 +62,6 @@ public static int IndexOfNonEscaped(string inString, char inChar, char escapeCha
public static string[] StringToArgs(string inString, int startIndex, int count, char separator = ' ', char escapeChar = '\\', char quoteChar = '\"', bool keepQuotes = false)
{
- if (inString == null)
- {
- return null;
- }
-
if (startIndex < 0 || startIndex >= inString.Length)
{
throw new ArgumentOutOfRangeException(nameof(startIndex));
@@ -80,8 +75,8 @@ public static string[] StringToArgs(string inString, int startIndex, int count,
if (inString.IsEmpty())
return Array.Empty();
- List args = new List();
- StringBuilder strBuilder = new StringBuilder();
+ List args = new();
+ StringBuilder strBuilder = new();
bool inQuotes = false;
bool escaped = false;
diff --git a/MultiAdmin/Utility/EmptyExtensions.cs b/MultiAdmin/Utility/EmptyExtensions.cs
index be39677..f7cf5d3 100644
--- a/MultiAdmin/Utility/EmptyExtensions.cs
+++ b/MultiAdmin/Utility/EmptyExtensions.cs
@@ -12,7 +12,7 @@ public static bool IsEmpty(this IEnumerable enumerable)
return !enumerable.Any();
}
- public static bool IsNullOrEmpty(this IEnumerable enumerable)
+ public static bool IsNullOrEmpty(this IEnumerable? enumerable)
{
return enumerable?.IsEmpty() ?? true;
}
@@ -22,17 +22,17 @@ public static bool IsEmpty(this Array array)
return array.Length <= 0;
}
- public static bool IsNullOrEmpty(this Array array)
+ public static bool IsNullOrEmpty(this Array? array)
{
return array?.IsEmpty() ?? true;
}
- public static bool IsEmpty(this T[] array)
+ public static bool IsEmpty(this T?[] array)
{
return array.Length <= 0;
}
- public static bool IsNullOrEmpty(this T[] array)
+ public static bool IsNullOrEmpty(this T?[]? array)
{
return array?.IsEmpty() ?? true;
}
@@ -42,7 +42,7 @@ public static bool IsEmpty(this ICollection collection)
return collection.Count <= 0;
}
- public static bool IsNullOrEmpty(this ICollection collection)
+ public static bool IsNullOrEmpty(this ICollection? collection)
{
return collection?.IsEmpty() ?? true;
}
@@ -52,17 +52,17 @@ public static bool IsEmpty(this List list)
return list.Count <= 0;
}
- public static bool IsNullOrEmpty(this List list)
+ public static bool IsNullOrEmpty(this List? list)
{
return list?.IsEmpty() ?? true;
}
- public static bool IsEmpty(this Dictionary dictionary)
+ public static bool IsEmpty(this Dictionary dictionary) where TKey : notnull
{
return dictionary.Count <= 0;
}
- public static bool IsNullOrEmpty(this Dictionary dictionary)
+ public static bool IsNullOrEmpty(this Dictionary? dictionary) where TKey : notnull
{
return dictionary?.IsEmpty() ?? true;
}
@@ -72,7 +72,7 @@ public static bool IsEmpty(this StringBuilder stringBuilder)
return stringBuilder.Length <= 0;
}
- public static bool IsNullOrEmpty(this StringBuilder stringBuilder)
+ public static bool IsNullOrEmpty(this StringBuilder? stringBuilder)
{
return stringBuilder?.IsEmpty() ?? true;
}
@@ -82,7 +82,7 @@ public static bool IsEmpty(this string @string)
return @string.Length <= 0;
}
- public static bool IsNullOrEmpty(this string @string)
+ public static bool IsNullOrEmpty(this string? @string)
{
return @string?.IsEmpty() ?? true;
}
diff --git a/MultiAdmin/Utility/StringEnumerableExtensions.cs b/MultiAdmin/Utility/StringEnumerableExtensions.cs
index 1d9aadb..e4fc972 100644
--- a/MultiAdmin/Utility/StringEnumerableExtensions.cs
+++ b/MultiAdmin/Utility/StringEnumerableExtensions.cs
@@ -6,12 +6,12 @@ namespace MultiAdmin.Utility
{
public static class StringEnumerableExtensions
{
- public static string JoinArgs(this IEnumerable args)
+ public static string JoinArgs(this IEnumerable args)
{
- StringBuilder argsStringBuilder = new StringBuilder();
- foreach (string arg in args)
+ StringBuilder argsStringBuilder = new();
+ foreach (string? arg in args)
{
- if (arg.IsNullOrEmpty())
+ if (string.IsNullOrEmpty(arg))
continue;
// Escape escape characters (if not on Windows) and quotation marks
diff --git a/MultiAdmin/Utility/StringExtensions.cs b/MultiAdmin/Utility/StringExtensions.cs
index eadb1f0..66007bd 100644
--- a/MultiAdmin/Utility/StringExtensions.cs
+++ b/MultiAdmin/Utility/StringExtensions.cs
@@ -4,7 +4,7 @@ namespace MultiAdmin.Utility
{
public static class StringExtensions
{
- public static bool Equals(this string input, string value, int startIndex, int count)
+ public static bool Equals(this string? input, string? value, int startIndex, int count)
{
if (input == null && value == null)
return true;
@@ -25,7 +25,7 @@ public static bool Equals(this string input, string value, int startIndex, int c
return true;
}
- public static bool Equals(this string input, string value, int startIndex)
+ public static bool Equals(this string? input, string? value, int startIndex)
{
if (input == null && value == null)
return true;
@@ -47,7 +47,7 @@ public static bool Equals(this string input, string value, int startIndex)
/// A escaped for use with
public static string EscapeFormat(this string input)
{
- return input?.Replace("{", "{{").Replace("}", "}}");
+ return input.Replace("{", "{{").Replace("}", "}}");
}
}
}
diff --git a/MultiAdmin/Utility/Utils.cs b/MultiAdmin/Utility/Utils.cs
index 137b54e..606b425 100644
--- a/MultiAdmin/Utility/Utils.cs
+++ b/MultiAdmin/Utility/Utils.cs
@@ -23,12 +23,10 @@ public static string TimeStampMessage(string message)
return string.IsNullOrEmpty(message) ? message : $"{TimeStamp} {message}";
}
- public static ColoredMessage[] TimeStampMessage(ColoredMessage[] message, ConsoleColor? color = null,
+ public static ColoredMessage?[] TimeStampMessage(ColoredMessage?[] message, ConsoleColor? color = null,
bool cloneMessages = false)
{
- if (message == null) return null;
-
- ColoredMessage[] newMessage = new ColoredMessage[message.Length + 1];
+ ColoredMessage?[] newMessage = new ColoredMessage?[message.Length + 1];
newMessage[0] = new ColoredMessage($"{TimeStamp} ", color);
if (cloneMessages)
@@ -45,13 +43,13 @@ public static ColoredMessage[] TimeStampMessage(ColoredMessage[] message, Consol
return newMessage;
}
- public static ColoredMessage[] TimeStampMessage(ColoredMessage message, ConsoleColor? color = null,
+ public static ColoredMessage?[] TimeStampMessage(ColoredMessage? message, ConsoleColor? color = null,
bool cloneMessages = false)
{
- return TimeStampMessage(new ColoredMessage[] {message}, color, cloneMessages);
+ return TimeStampMessage(new ColoredMessage?[] { message }, color, cloneMessages);
}
- public static string GetFullPathSafe(string path)
+ public static string? GetFullPathSafe(string? path)
{
return string.IsNullOrWhiteSpace(path) ? null : Path.GetFullPath(path);
}
@@ -93,7 +91,7 @@ public static bool StringMatches(string input, string pattern, char wildCard = W
return false;
Program.LogDebug(nameof(StringMatches),
- $"Matching \"{wildCardSection}\" with \"{input.Substring(matchIndex)}\"...");
+ $"Matching \"{wildCardSection}\" with \"{input[matchIndex..]}\"...");
if (matchIndex <= 0 && pattern[0] != wildCard)
{
@@ -130,25 +128,25 @@ public static bool StringMatches(string input, string pattern, char wildCard = W
}
Program.LogDebug(nameof(StringMatches),
- $"Done matching. Matches = {matchIndex == input.Length || wildCardSections[wildCardSections.Length - 1].IsEmpty()}.");
+ $"Done matching. Matches = {matchIndex == input.Length || wildCardSections[^1].IsEmpty()}.");
- return matchIndex == input.Length || wildCardSections[wildCardSections.Length - 1].IsEmpty();
+ return matchIndex == input.Length || wildCardSections[^1].IsEmpty();
}
- public static bool InputMatchesAnyPattern(string input, params string[] namePatterns)
+ public static bool InputMatchesAnyPattern(string input, params string[]? namePatterns)
{
- return !namePatterns.IsNullOrEmpty() && namePatterns.Any(namePattern => StringMatches(input, namePattern));
+ return namePatterns != null && namePatterns.Length > 0 && namePatterns.Any(namePattern => StringMatches(input, namePattern));
}
- private static bool PassesWhitelistAndBlacklist(string toCheck, string[] whitelist = null,
- string[] blacklist = null)
+ private static bool PassesWhitelistAndBlacklist(string toCheck, string[]? whitelist = null,
+ string[]? blacklist = null)
{
return (whitelist.IsNullOrEmpty() || InputMatchesAnyPattern(toCheck, whitelist)) &&
- (blacklist.IsNullOrEmpty() || !InputMatchesAnyPattern(toCheck, blacklist));
+ (blacklist.IsNullOrEmpty() || !InputMatchesAnyPattern(toCheck, blacklist));
}
- public static void CopyAll(DirectoryInfo source, DirectoryInfo target, string[] fileWhitelist = null,
- string[] fileBlacklist = null)
+ public static void CopyAll(DirectoryInfo source, DirectoryInfo target, string[]? fileWhitelist = null,
+ string[]? fileBlacklist = null)
{
// If the target directory is the same as the source directory
if (source.FullName == target.FullName)
@@ -176,8 +174,8 @@ public static void CopyAll(DirectoryInfo source, DirectoryInfo target, string[]
}
}
- public static void CopyAll(string source, string target, string[] fileWhitelist = null,
- string[] fileBlacklist = null)
+ public static void CopyAll(string source, string target, string[]? fileWhitelist = null,
+ string[]? fileBlacklist = null)
{
CopyAll(new DirectoryInfo(source), new DirectoryInfo(target), fileWhitelist, fileBlacklist);
}
diff --git a/MultiAdmin/nuget.config b/MultiAdmin/nuget.config
deleted file mode 100644
index 7c26348..0000000
--- a/MultiAdmin/nuget.config
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/README.md b/README.md
index 3378da4..02e350c 100644
--- a/README.md
+++ b/README.md
@@ -27,7 +27,7 @@ Make sure that you are running Mono 5.18.0 or higher, otherwise you might have i
- Config Generator: Generates a full default MultiAdmin config file
- Config Reload: Reloads the MultiAdmin configuration file
- Exit Command: Adds a graceful exit command
-- Folder Copy Round Queue: Copies files from folders in a queue
+- File Copy Round Queue: Copies files from folders in a queue
- GitHub Generator: Generates a GitHub README file outlining all the features/commands
- Help: Display a full list of MultiAdmin commands and in game commands
- Restart On Low Memory: Restarts the server if the working memory becomes too low
@@ -53,6 +53,7 @@ This does not include ingame commands, for a full list type `HELP` in MultiAdmin
The arguments available for running MultiAdmin with
- `--headless` or `-h`: Runs MultiAdmin in headless mode, this makes MultiAdmin not accept any input at all and only output to log files, not in console (Note: This argument is inherited by processes started by this MultiAdmin process)
+- `--input-system ` or `-is `: The [ConsoleInputSystem](#consoleinputsystem) to use for this MultiAdmin instance (Note: This is used over the config option `console_input_system` and is inherited by processes started by this MultiAdmin process)
- `--server-id ` or `-id `: The Server ID to run this MultiAdmin instance with a config location (`--config` or `-c`) so that it reads the configs from the location, but stores the logs in the Server ID's folder
- `--config ` or `-c `: The config location to use for this MultiAdmin instance (Note: This is used over the config option `config_location`)
- `--port ` or `-p `: The port to use for this MultiAdmin instance (Note: This is used over the config option `port` and is inherited by processes started by this MultiAdmin process)
@@ -61,6 +62,13 @@ The arguments available for running MultiAdmin with
All configuration settings go into a file named `scp_multiadmin.cfg` in the same directory as MultiAdmin.exe or in your server directory within the `servers_folder` value defined in the global configuration file
Any configuration files within the directory defined by `servers_folder` will have it's values used for that server over the global configuration file
+Example config:
+```yml
+port: 7777
+max_memory: 2048
+config_location: "/home/container/Server Config"
+```
+
Config Option | Value Type | Default Value | Description
--- | :---: | :---: | :------:
config_location | String | **Empty** | The default location for the game to use for storing configuration files (a directory)
@@ -73,7 +81,7 @@ multiadmin_debug_log | Boolean | True | Enables MultiAdmin debug logging, this l
multiadmin_debug_log_blacklist | String List | HandleMessage, StringMatches, MessageListener | Which tags to block for MultiAdmin debug logging
multiadmin_debug_log_whitelist | String List | **Empty** | Which tags to log for MultiAdmin debug logging (Defaults to logging all if none are provided)
use_new_input_system | Boolean | True | **OBSOLETE: Use `console_input_system` instead, this config option may be removed in a future version of MultiAdmin.** Whether to use the new input system, if false, the original input system will be used
-console_input_system | [ConsoleInputSystem](#ConsoleInputSystem) | New | Which console input system to use
+console_input_system | [ConsoleInputSystem](#consoleinputsystem) | New | Which console input system to use
hide_input | Boolean | False | Whether to hide console input, if true, typed input will not be printed
port | Unsigned Integer | 7777 | The port for the server to use
copy_from_folder_on_reload | String | **Empty** | The location of a folder to copy files from into the folder defined by `config_location` whenever the configuration file is reloaded