diff --git a/Application/Application.csproj b/Application/Application.csproj
index c4d3a54df..b12c87b08 100644
--- a/Application/Application.csproj
+++ b/Application/Application.csproj
@@ -6,7 +6,7 @@
2.2.2
false
RaidMax.IW4MAdmin.Application
- 2.2.7.1
+ 2.2.7.2
RaidMax
Forever None
IW4MAdmin
@@ -32,8 +32,8 @@
true
true
- 2.2.7.1
- 2.2.7.1
+ 2.2.7.2
+ 2.2.7.2
7.1
@@ -47,12 +47,6 @@
-
-
- Always
-
-
-
diff --git a/Application/ApplicationManager.cs b/Application/ApplicationManager.cs
index 723b5c034..2175e01f6 100644
--- a/Application/ApplicationManager.cs
+++ b/Application/ApplicationManager.cs
@@ -15,6 +15,7 @@ using SharedLibraryCore.Interfaces;
using SharedLibraryCore.Objects;
using SharedLibraryCore.Services;
using System;
+using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
@@ -26,7 +27,7 @@ namespace IW4MAdmin.Application
{
public class ApplicationManager : IManager
{
- private List _servers;
+ private ConcurrentBag _servers;
public List Servers => _servers.OrderByDescending(s => s.ClientNum).ToList();
public ILogger Logger => GetLogger(0);
public bool Running { get; private set; }
@@ -41,8 +42,9 @@ namespace IW4MAdmin.Application
public IList AdditionalRConParsers { get; }
public IList AdditionalEventParsers { get; }
public ITokenAuthentication TokenAuthenticator { get; }
+ public CancellationToken CancellationToken => _tokenSource.Token;
public string ExternalIPAddress { get; private set; }
-
+ public bool IsRestartRequested { get; private set; }
static ApplicationManager Instance;
readonly List TaskStatuses;
List Commands;
@@ -52,16 +54,16 @@ namespace IW4MAdmin.Application
readonly PenaltyService PenaltySvc;
public BaseConfigurationHandler ConfigHandler;
GameEventHandler Handler;
- ManualResetEventSlim OnQuit;
readonly IPageList PageList;
readonly SemaphoreSlim ProcessingEvent = new SemaphoreSlim(1, 1);
readonly Dictionary Loggers = new Dictionary();
private readonly MetaService _metaService;
private readonly TimeSpan _throttleTimeout = new TimeSpan(0, 1, 0);
+ private readonly CancellationTokenSource _tokenSource;
private ApplicationManager()
{
- _servers = new List();
+ _servers = new ConcurrentBag();
Commands = new List();
TaskStatuses = new List();
MessageTokens = new List();
@@ -70,7 +72,6 @@ namespace IW4MAdmin.Application
PenaltySvc = new PenaltyService();
ConfigHandler = new BaseConfigurationHandler("IW4MAdminSettings");
StartTime = DateTime.UtcNow;
- OnQuit = new ManualResetEventSlim();
PageList = new PageList();
AdditionalEventParsers = new List();
AdditionalRConParsers = new List();
@@ -78,6 +79,7 @@ namespace IW4MAdmin.Application
OnServerEvent += EventApi.OnGameEvent;
TokenAuthenticator = new TokenAuthentication();
_metaService = new MetaService();
+ _tokenSource = new CancellationTokenSource();
}
private async void OnGameEvent(object sender, GameEventArgs args)
@@ -155,12 +157,12 @@ namespace IW4MAdmin.Application
return Instance ?? (Instance = new ApplicationManager());
}
- public async Task UpdateServerStates(CancellationToken token)
+ public async Task UpdateServerStates()
{
// store the server hash code and task for it
var runningUpdateTasks = new Dictionary();
- while (Running)
+ while (!_tokenSource.IsCancellationRequested)
{
// select the server ids that have completed the update task
var serverTasksToRemove = runningUpdateTasks
@@ -191,10 +193,11 @@ namespace IW4MAdmin.Application
{
try
{
- await server.ProcessUpdatesAsync(token);
+ await server.ProcessUpdatesAsync(_tokenSource.Token);
+
if (server.Throttled)
{
- await Task.Delay((int)_throttleTimeout.TotalMilliseconds);
+ await Task.Delay((int)_throttleTimeout.TotalMilliseconds, _tokenSource.Token);
}
}
@@ -218,7 +221,7 @@ namespace IW4MAdmin.Application
#endif
try
{
- await Task.Delay(ConfigHandler.Configuration().RConPollRate, token);
+ await Task.Delay(ConfigHandler.Configuration().RConPollRate, _tokenSource.Token);
}
// if a cancellation is received, we want to return immediately
catch { break; }
@@ -341,7 +344,7 @@ namespace IW4MAdmin.Application
GetApplicationSettings().Configuration()?.DatabaseProvider))
{
await new ContextSeed(db).Seed();
- }
+ }
#endregion
#region COMMANDS
@@ -351,6 +354,7 @@ namespace IW4MAdmin.Application
}
Commands.Add(new CQuit());
+ Commands.Add(new CRestart());
Commands.Add(new CKick());
Commands.Add(new CSay());
Commands.Add(new CTempBan());
@@ -517,7 +521,12 @@ namespace IW4MAdmin.Application
MetaService.AddRuntimeMeta(getPenaltyMeta);
#endregion
- #region INIT
+ await InitializeServers();
+ }
+
+ private async Task InitializeServers()
+ {
+ var config = ConfigHandler.Configuration();
int successServers = 0;
Exception lastException = null;
@@ -531,10 +540,7 @@ namespace IW4MAdmin.Application
var ServerInstance = new IW4MServer(this, Conf);
await ServerInstance.Initialize();
- lock (_servers)
- {
- _servers.Add(ServerInstance);
- }
+ _servers.Add(ServerInstance);
Logger.WriteVerbose(Utilities.CurrentLocalization.LocalizationIndex["MANAGER_MONITORING_TEXT"].FormatExt(ServerInstance.Hostname));
// add the start event for this server
@@ -577,25 +583,25 @@ namespace IW4MAdmin.Application
throw lastException;
}
}
- #endregion
}
- private async Task SendHeartbeat(object state)
- {
- var heartbeatState = (HeartbeatState)state;
- while (Running)
+ private async Task SendHeartbeat()
+ {
+ bool connected = false;
+
+ while (!_tokenSource.IsCancellationRequested)
{
- if (!heartbeatState.Connected)
+ if (!connected)
{
try
{
await Heartbeat.Send(this, true);
- heartbeatState.Connected = true;
+ connected = true;
}
catch (Exception e)
{
- heartbeatState.Connected = false;
+ connected = false;
Logger.WriteWarning($"Could not connect to heartbeat server - {e.Message}");
}
}
@@ -621,7 +627,7 @@ namespace IW4MAdmin.Application
{
if (((RestEase.ApiException)ex).StatusCode == System.Net.HttpStatusCode.Unauthorized)
{
- heartbeatState.Connected = false;
+ connected = false;
}
}
}
@@ -631,9 +637,10 @@ namespace IW4MAdmin.Application
Logger.WriteWarning($"Could not send heartbeat - {e.Message}");
if (e.StatusCode == System.Net.HttpStatusCode.Unauthorized)
{
- heartbeatState.Connected = false;
+ connected = false;
}
}
+
catch (Exception e)
{
Logger.WriteWarning($"Could not send heartbeat - {e.Message}");
@@ -643,31 +650,32 @@ namespace IW4MAdmin.Application
try
{
- await Task.Delay(30000, heartbeatState.Token);
+ await Task.Delay(30000, _tokenSource.Token);
}
catch { break; }
}
}
- public void Start()
+ public Task Start()
{
- var tokenSource = new CancellationTokenSource();
- // this needs to be run seperately from the main thread
- _ = Task.Run(() => SendHeartbeat(new HeartbeatState() { Token = tokenSource.Token }));
- _ = Task.Run(() => UpdateServerStates(tokenSource.Token));
-
- while (Running)
+ return Task.WhenAll(new[]
{
- OnQuit.Wait();
- tokenSource.Cancel();
- OnQuit.Reset();
- }
+ SendHeartbeat(),
+ UpdateServerStates()
+ });
}
public void Stop()
{
+ _tokenSource.Cancel();
Running = false;
- OnQuit.Set();
+ Instance = null;
+ }
+
+ public void Restart()
+ {
+ IsRestartRequested = true;
+ Stop();
}
public ILogger GetLogger(long serverId)
@@ -725,21 +733,11 @@ namespace IW4MAdmin.Application
return ConfigHandler;
}
- public bool ShutdownRequested()
- {
- return !Running;
- }
-
public IEventHandler GetEventHandler()
{
return Handler;
}
- public void SetHasEvent()
- {
-
- }
-
public IList GetPluginAssemblies()
{
return SharedLibraryCore.Plugins.PluginImporter.PluginAssemblies.Union(SharedLibraryCore.Plugins.PluginImporter.Assemblies).ToList();
diff --git a/Application/BuildScripts/PostPublish.bat b/Application/BuildScripts/PostPublish.bat
index 0f159edc1..22d06a63a 100644
--- a/Application/BuildScripts/PostPublish.bat
+++ b/Application/BuildScripts/PostPublish.bat
@@ -108,8 +108,8 @@ if "%CurrentConfiguration%" == "Release" (
)
echo making start scripts
-@(echo @echo off && echo @title IW4MAdmin && echo dotnet Lib\IW4MAdmin.dll && echo pause) > "%SolutionDir%Publish\WindowsPrerelease\StartIW4MAdmin.cmd"
-@(echo @echo off && echo @title IW4MAdmin && echo dotnet Lib\IW4MAdmin.dll && echo pause) > "%SolutionDir%Publish\Windows\StartIW4MAdmin.cmd"
+@(echo @echo off && echo @title IW4MAdmin && echo set DOTNET_CLI_TELEMETRY_OPTOUT=1 && echo dotnet Lib\IW4MAdmin.dll && echo pause) > "%SolutionDir%Publish\WindowsPrerelease\StartIW4MAdmin.cmd"
+@(echo @echo off && echo @title IW4MAdmin && echo set DOTNET_CLI_TELEMETRY_OPTOUT=1 && echo dotnet Lib\IW4MAdmin.dll && echo pause) > "%SolutionDir%Publish\Windows\StartIW4MAdmin.cmd"
-@(echo #!/bin/bash && echo dotnet Lib/IW4MAdmin.dll) > "%SolutionDir%Publish\WindowsPrerelease\StartIW4MAdmin.sh"
-@(echo #!/bin/bash && echo dotnet Lib/IW4MAdmin.dll) > "%SolutionDir%Publish\Windows\StartIW4MAdmin.sh"
+@(echo #!/bin/bash && echo export DOTNET_CLI_TELEMETRY_OPTOUT=1 && echo dotnet Lib/IW4MAdmin.dll) > "%SolutionDir%Publish\WindowsPrerelease\StartIW4MAdmin.sh"
+@(echo #!/bin/bash && echo export DOTNET_CLI_TELEMETRY_OPTOUT=1 && echo dotnet Lib/IW4MAdmin.dll) > "%SolutionDir%Publish\Windows\StartIW4MAdmin.sh"
diff --git a/Application/DefaultSettings.json b/Application/DefaultSettings.json
index bd953c342..811565d16 100644
--- a/Application/DefaultSettings.json
+++ b/Application/DefaultSettings.json
@@ -16,7 +16,7 @@
"Keep grenade launcher use to a minimum",
"Balance teams at ALL times"
],
- "DisallowedClientNames": ["Unknown Soldier", "VickNet", "UnknownSoldier", "CHEATER"],
+ "DisallowedClientNames": [ "Unknown Soldier", "VickNet", "UnknownSoldier", "CHEATER", "Play77" ],
"QuickMessages": [
{
"Game": "IW4",
@@ -517,6 +517,10 @@
"Alias": "Hanoi",
"Name": "mp_hanoi"
},
+ {
+ "Alias": "Havana",
+ "Name": "mp_cairo"
+ },
{
"Alias": "Hazard",
"Name": "mp_golfcourse"
diff --git a/Application/IO/GameLogEventDetection.cs b/Application/IO/GameLogEventDetection.cs
index 3af8d2930..35cb588f3 100644
--- a/Application/IO/GameLogEventDetection.cs
+++ b/Application/IO/GameLogEventDetection.cs
@@ -8,10 +8,10 @@ namespace IW4MAdmin.Application.IO
{
class GameLogEventDetection
{
- Server Server;
- long PreviousFileSize;
- IGameLogReader Reader;
- readonly string GameLogFile;
+ private long previousFileSize;
+ private readonly Server _server;
+ private readonly IGameLogReader _reader;
+ private readonly string _gameLogFile;
class EventState
{
@@ -21,16 +21,16 @@ namespace IW4MAdmin.Application.IO
public GameLogEventDetection(Server server, string gameLogPath, Uri gameLogServerUri)
{
- GameLogFile = gameLogPath;
- Reader = gameLogServerUri != null ? new GameLogReaderHttp(gameLogServerUri, gameLogPath, server.EventParser) : Reader = new GameLogReader(gameLogPath, server.EventParser);
- Server = server;
+ _gameLogFile = gameLogPath;
+ _reader = gameLogServerUri != null ? new GameLogReaderHttp(gameLogServerUri, gameLogPath, server.EventParser) : _reader = new GameLogReader(gameLogPath, server.EventParser);
+ _server = server;
}
public async Task PollForChanges()
{
- while (!Server.Manager.ShutdownRequested())
+ while (!_server.Manager.CancellationToken.IsCancellationRequested)
{
- if (Server.IsInitialized)
+ if (_server.IsInitialized)
{
try
{
@@ -39,39 +39,40 @@ namespace IW4MAdmin.Application.IO
catch (Exception e)
{
- Server.Logger.WriteWarning($"Failed to update log event for {Server.EndPoint}");
- Server.Logger.WriteDebug($"Exception: {e.Message}");
- Server.Logger.WriteDebug($"StackTrace: {e.StackTrace}");
+ _server.Logger.WriteWarning($"Failed to update log event for {_server.EndPoint}");
+ _server.Logger.WriteDebug($"Exception: {e.Message}");
+ _server.Logger.WriteDebug($"StackTrace: {e.StackTrace}");
}
}
- Thread.Sleep(Reader.UpdateInterval);
+
+ await Task.Delay(_reader.UpdateInterval, _server.Manager.CancellationToken);
}
}
private async Task UpdateLogEvents()
{
- long fileSize = Reader.Length;
+ long fileSize = _reader.Length;
- if (PreviousFileSize == 0)
- PreviousFileSize = fileSize;
+ if (previousFileSize == 0)
+ previousFileSize = fileSize;
- long fileDiff = fileSize - PreviousFileSize;
+ long fileDiff = fileSize - previousFileSize;
// this makes the http log get pulled
if (fileDiff < 1 && fileSize != -1)
return;
- PreviousFileSize = fileSize;
+ previousFileSize = fileSize;
- var events = await Reader.ReadEventsFromLog(Server, fileDiff, 0);
+ var events = await _reader.ReadEventsFromLog(_server, fileDiff, 0);
foreach (var ev in events)
{
- Server.Manager.GetEventHandler().AddEvent(ev);
- await ev.WaitAsync();
+ _server.Manager.GetEventHandler().AddEvent(ev);
+ await ev.WaitAsync(Utilities.DefaultCommandTimeout, _server.Manager.CancellationToken);
}
- PreviousFileSize = fileSize;
+ previousFileSize = fileSize;
}
}
}
diff --git a/Application/IW4MServer.cs b/Application/IW4MServer.cs
index e63f836ca..903df21bf 100644
--- a/Application/IW4MServer.cs
+++ b/Application/IW4MServer.cs
@@ -296,6 +296,20 @@ namespace IW4MAdmin
Target = E.Target,
Reason = E.Data
});
+
+ Penalty newReport = new Penalty()
+ {
+ Type = Penalty.PenaltyType.Report,
+ Expires = DateTime.UtcNow,
+ Offender = E.Target,
+ Offense = E.Message,
+ Punisher = E.Origin,
+ Active = true,
+ When = DateTime.UtcNow,
+ Link = E.Target.AliasLink
+ };
+
+ await Manager.GetPenaltyService().Create(newReport);
}
else if (E.Type == GameEvent.EventType.TempBan)
@@ -548,7 +562,7 @@ namespace IW4MAdmin
try
{
#region SHUTDOWN
- if (Manager.ShutdownRequested())
+ if (Manager.CancellationToken.IsCancellationRequested)
{
foreach (var client in GetClientsAsList())
{
@@ -560,7 +574,7 @@ namespace IW4MAdmin
};
Manager.GetEventHandler().AddEvent(e);
- await e.WaitAsync();
+ await e.WaitAsync(Utilities.DefaultCommandTimeout, Manager.CancellationToken);
}
foreach (var plugin in SharedLibraryCore.Plugins.PluginImporter.ActivePlugins)
@@ -597,7 +611,7 @@ namespace IW4MAdmin
waiterList.Add(e);
}
// wait for all the disconnect tasks to finish
- await Task.WhenAll(waiterList.Select(e => e.WaitAsync(10 * 1000)));
+ await Task.WhenAll(waiterList.Select(e => e.WaitAsync(Utilities.DefaultCommandTimeout, Manager.CancellationToken)));
waiterList.Clear();
// this are our new connecting clients
@@ -621,7 +635,7 @@ namespace IW4MAdmin
}
// wait for all the connect tasks to finish
- await Task.WhenAll(waiterList.Select(e => e.WaitAsync(10 * 1000)));
+ await Task.WhenAll(waiterList.Select(e => e.WaitAsync(Utilities.DefaultCommandTimeout, Manager.CancellationToken)));
waiterList.Clear();
// these are the clients that have updated
@@ -638,7 +652,7 @@ namespace IW4MAdmin
waiterList.Add(e);
}
- await Task.WhenAll(waiterList.Select(e => e.WaitAsync(10 * 1000)));
+ await Task.WhenAll(waiterList.Select(e => e.WaitAsync(Utilities.DefaultCommandTimeout, Manager.CancellationToken)));
if (ConnectionErrors > 0)
{
diff --git a/Application/Main.cs b/Application/Main.cs
index 841226802..b56b26144 100644
--- a/Application/Main.cs
+++ b/Application/Main.cs
@@ -1,204 +1,221 @@
using IW4MAdmin.Application.Migration;
using SharedLibraryCore;
-using SharedLibraryCore.Localization;
using System;
-using System.IO;
using System.Text;
-using System.Threading;
using System.Threading.Tasks;
namespace IW4MAdmin.Application
{
public class Program
{
- static public double Version { get; private set; }
- static public ApplicationManager ServerManager;
- private static ManualResetEventSlim OnShutdownComplete = new ManualResetEventSlim();
+ public static double Version { get; private set; } = Utilities.GetVersionAsDouble();
+ public static ApplicationManager ServerManager;
+ private static Task ApplicationTask;
- public static void Main(string[] args)
+ ///
+ /// entrypoint of the application
+ ///
+ ///
+ public static async Task Main()
{
AppDomain.CurrentDomain.SetData("DataDirectory", Utilities.OperatingDirectory);
+
Console.OutputEncoding = Encoding.UTF8;
Console.ForegroundColor = ConsoleColor.Gray;
- Version = Utilities.GetVersionAsDouble();
+ Console.CancelKeyPress += new ConsoleCancelEventHandler(OnCancelKey);
Console.WriteLine("=====================================================");
- Console.WriteLine(" IW4M ADMIN");
+ Console.WriteLine(" IW4MAdmin");
Console.WriteLine(" by RaidMax ");
Console.WriteLine($" Version {Utilities.GetVersionAsString()}");
Console.WriteLine("=====================================================");
- Index loc = null;
+ await LaunchAsync();
+ }
+ ///
+ /// event callback executed when the control + c combination is detected
+ /// gracefully stops the server manager and waits for all tasks to finish
+ ///
+ ///
+ ///
+ private static async void OnCancelKey(object sender, ConsoleCancelEventArgs e)
+ {
+ ServerManager?.Stop();
+ await ApplicationTask;
+ }
+
+ ///
+ /// task that initializes application and starts the application monitoring and runtime tasks
+ ///
+ ///
+ private static async Task LaunchAsync()
+ {
+ restart:
try
{
ServerManager = ApplicationManager.GetInstance();
var configuration = ServerManager.GetApplicationSettings().Configuration();
+ Localization.Configure.Initialize(configuration?.EnableCustomLocale ?? false ? (configuration.CustomLocale ?? "windows-1252") : "windows-1252");
- if (configuration != null)
- {
- Localization.Configure.Initialize(configuration.EnableCustomLocale ? (configuration.CustomLocale ?? "windows-1252") : "windows-1252");
- }
-
- else
- {
- Localization.Configure.Initialize();
- }
-
- loc = Utilities.CurrentLocalization.LocalizationIndex;
- Console.CancelKeyPress += new ConsoleCancelEventHandler(OnCancelKey);
-
- CheckDirectories();
- // do any needed migrations
- // todo: move out
+ // do any needed housekeeping file/folder migrations
ConfigurationMigration.MoveConfigFolder10518(null);
+ ConfigurationMigration.CheckDirectories();
- ServerManager.Logger.WriteInfo($"Version is {Version}");
+ ServerManager.Logger.WriteInfo(Utilities.CurrentLocalization.LocalizationIndex["MANAGER_VERSION"].FormatExt(Version));
- var api = API.Master.Endpoint.Get();
-
- var version = new API.Master.VersionInfo()
- {
- CurrentVersionStable = 99.99f
- };
-
- try
- {
- version = api.GetVersion().Result;
- }
-
- catch (Exception e)
- {
- ServerManager.Logger.WriteWarning(loc["MANAGER_VERSION_FAIL"]);
- while (e.InnerException != null)
- {
- e = e.InnerException;
- }
-
- ServerManager.Logger.WriteDebug(e.Message);
- }
-
- if (version.CurrentVersionStable == 99.99f)
- {
- Console.ForegroundColor = ConsoleColor.Red;
- Console.WriteLine(loc["MANAGER_VERSION_FAIL"]);
- Console.ForegroundColor = ConsoleColor.Gray;
- }
-
-#if !PRERELEASE
- else if (version.CurrentVersionStable > Version)
- {
- Console.ForegroundColor = ConsoleColor.DarkYellow;
- Console.WriteLine($"IW4MAdmin {loc["MANAGER_VERSION_UPDATE"]} [v{version.CurrentVersionStable.ToString("0.0")}]");
- Console.WriteLine(loc["MANAGER_VERSION_CURRENT"].FormatExt($"[v{Version.ToString("0.0")}]"));
- Console.ForegroundColor = ConsoleColor.Gray;
- }
-#else
- else if (version.CurrentVersionPrerelease > Version)
- {
- Console.ForegroundColor = ConsoleColor.DarkYellow;
- Console.WriteLine($"IW4MAdmin-Prerelease {loc["MANAGER_VERSION_UPDATE"]} [v{version.CurrentVersionPrerelease.ToString("0.0")}-pr]");
- Console.WriteLine(loc["MANAGER_VERSION_CURRENT"].FormatExt($"[v{Version.ToString("0.0")}-pr]"));
- Console.ForegroundColor = ConsoleColor.Gray;
- }
-#endif
- else
- {
- Console.ForegroundColor = ConsoleColor.Green;
- Console.WriteLine(loc["MANAGER_VERSION_SUCCESS"]);
- Console.ForegroundColor = ConsoleColor.Gray;
- }
-
- ServerManager.Init().Wait();
-
- var consoleTask = Task.Run(async () =>
- {
- string userInput;
- var Origin = Utilities.IW4MAdminClient(ServerManager.Servers[0]);
-
- do
- {
- userInput = Console.ReadLine();
-
- if (userInput?.ToLower() == "quit")
- {
- ServerManager.Stop();
- }
-
- if (ServerManager.Servers.Count == 0)
- {
- Console.WriteLine(loc["MANAGER_CONSOLE_NOSERV"]);
- continue;
- }
-
- if (userInput?.Length > 0)
- {
- GameEvent E = new GameEvent()
- {
- Type = GameEvent.EventType.Command,
- Data = userInput,
- Origin = Origin,
- Owner = ServerManager.Servers[0]
- };
-
- ServerManager.GetEventHandler().AddEvent(E);
- await E.WaitAsync(30 * 1000);
- }
- Console.Write('>');
-
- } while (ServerManager.Running);
- });
+ await CheckVersion();
+ await ServerManager.Init();
}
catch (Exception e)
{
+ var loc = Utilities.CurrentLocalization.LocalizationIndex;
string failMessage = loc == null ? "Failed to initalize IW4MAdmin" : loc["MANAGER_INIT_FAIL"];
string exitMessage = loc == null ? "Press any key to exit..." : loc["MANAGER_EXIT"];
Console.WriteLine(failMessage);
+
while (e.InnerException != null)
{
e = e.InnerException;
}
+
Console.WriteLine(e.Message);
Console.WriteLine(exitMessage);
Console.ReadKey();
- return;
}
- if (ServerManager.GetApplicationSettings().Configuration().EnableWebFront)
+ try
{
- Task.Run(() => WebfrontCore.Program.Init(ServerManager));
+ ApplicationTask = RunApplicationTasksAsync();
+ await ApplicationTask;
}
- OnShutdownComplete.Reset();
- ServerManager.Start();
- ServerManager.Logger.WriteVerbose(loc["MANAGER_SHUTDOWN_SUCCESS"]);
- OnShutdownComplete.Set();
+ catch { }
+
+ if (ServerManager.IsRestartRequested)
+ {
+ goto restart;
+ }
}
- private static void OnCancelKey(object sender, ConsoleCancelEventArgs e)
+ ///
+ /// runs the core application tasks
+ ///
+ ///
+ private static async Task RunApplicationTasksAsync()
{
- ServerManager.Stop();
- OnShutdownComplete.Wait();
+ var webfrontTask = ServerManager.GetApplicationSettings().Configuration().EnableWebFront ?
+ WebfrontCore.Program.Init(ServerManager, ServerManager.CancellationToken) :
+ Task.CompletedTask;
+
+ var tasks = new[]
+ {
+ webfrontTask,
+ ReadConsoleInput(),
+ ServerManager.Start(),
+ };
+
+ await Task.WhenAll(tasks);
+
+ ServerManager.Logger.WriteVerbose(Utilities.CurrentLocalization.LocalizationIndex["MANAGER_SHUTDOWN_SUCCESS"]);
}
- static void CheckDirectories()
+ ///
+ /// checks for latest version of the application
+ /// notifies user if an update is available
+ ///
+ ///
+ private static async Task CheckVersion()
{
- if (!Directory.Exists(Path.Join(Utilities.OperatingDirectory, "Plugins")))
+ var api = API.Master.Endpoint.Get();
+ var loc = Utilities.CurrentLocalization.LocalizationIndex;
+
+ var version = new API.Master.VersionInfo()
{
- Directory.CreateDirectory(Path.Join(Utilities.OperatingDirectory, "Plugins"));
+ CurrentVersionStable = 99.99f
+ };
+
+ try
+ {
+ version = await api.GetVersion();
}
- if (!Directory.Exists(Path.Join(Utilities.OperatingDirectory, "Database")))
+ catch (Exception e)
{
- Directory.CreateDirectory(Path.Join(Utilities.OperatingDirectory, "Database"));
+ ServerManager.Logger.WriteWarning(loc["MANAGER_VERSION_FAIL"]);
+ while (e.InnerException != null)
+ {
+ e = e.InnerException;
+ }
+
+ ServerManager.Logger.WriteDebug(e.Message);
}
- if (!Directory.Exists(Path.Join(Utilities.OperatingDirectory, "Log")))
+ if (version.CurrentVersionStable == 99.99f)
{
- Directory.CreateDirectory(Path.Join(Utilities.OperatingDirectory, "Log"));
+ Console.ForegroundColor = ConsoleColor.Red;
+ Console.WriteLine(loc["MANAGER_VERSION_FAIL"]);
+ Console.ForegroundColor = ConsoleColor.Gray;
+ }
+
+#if !PRERELEASE
+ else if (version.CurrentVersionStable > Version)
+ {
+ Console.ForegroundColor = ConsoleColor.DarkYellow;
+ Console.WriteLine($"IW4MAdmin {loc["MANAGER_VERSION_UPDATE"]} [v{version.CurrentVersionStable.ToString("0.0")}]");
+ Console.WriteLine(loc["MANAGER_VERSION_CURRENT"].FormatExt($"[v{Version.ToString("0.0")}]"));
+ Console.ForegroundColor = ConsoleColor.Gray;
+ }
+#else
+ else if (version.CurrentVersionPrerelease > Version)
+ {
+ Console.ForegroundColor = ConsoleColor.DarkYellow;
+ Console.WriteLine($"IW4MAdmin-Prerelease {loc["MANAGER_VERSION_UPDATE"]} [v{version.CurrentVersionPrerelease.ToString("0.0")}-pr]");
+ Console.WriteLine(loc["MANAGER_VERSION_CURRENT"].FormatExt($"[v{Version.ToString("0.0")}-pr]"));
+ Console.ForegroundColor = ConsoleColor.Gray;
+ }
+#endif
+ else
+ {
+ Console.ForegroundColor = ConsoleColor.Green;
+ Console.WriteLine(loc["MANAGER_VERSION_SUCCESS"]);
+ Console.ForegroundColor = ConsoleColor.Gray;
+ }
+ }
+
+ ///
+ /// reads input from the console and executes entered commands on the default server
+ ///
+ ///
+ private static async Task ReadConsoleInput()
+ {
+ string lastCommand;
+ var Origin = Utilities.IW4MAdminClient(ServerManager.Servers[0]);
+
+ while (!ServerManager.CancellationToken.IsCancellationRequested)
+ {
+ lastCommand = Console.ReadLine();
+
+ if (lastCommand?.Length > 0)
+ {
+ if (lastCommand?.Length > 0)
+ {
+ GameEvent E = new GameEvent()
+ {
+ Type = GameEvent.EventType.Command,
+ Data = lastCommand,
+ Origin = Origin,
+ Owner = ServerManager.Servers[0]
+ };
+
+ ServerManager.GetEventHandler().AddEvent(E);
+ await E.WaitAsync(Utilities.DefaultCommandTimeout, ServerManager.CancellationToken);
+ Console.Write('>');
+ }
+ }
}
}
}
diff --git a/Application/Migration/ConfigurationMigration.cs b/Application/Migration/ConfigurationMigration.cs
index 8edd25152..487f7e735 100644
--- a/Application/Migration/ConfigurationMigration.cs
+++ b/Application/Migration/ConfigurationMigration.cs
@@ -15,6 +15,27 @@ namespace IW4MAdmin.Application.Migration
///
class ConfigurationMigration
{
+ ///
+ /// ensures required directories are created
+ ///
+ public static void CheckDirectories()
+ {
+ if (!Directory.Exists(Path.Join(Utilities.OperatingDirectory, "Plugins")))
+ {
+ Directory.CreateDirectory(Path.Join(Utilities.OperatingDirectory, "Plugins"));
+ }
+
+ if (!Directory.Exists(Path.Join(Utilities.OperatingDirectory, "Database")))
+ {
+ Directory.CreateDirectory(Path.Join(Utilities.OperatingDirectory, "Database"));
+ }
+
+ if (!Directory.Exists(Path.Join(Utilities.OperatingDirectory, "Log")))
+ {
+ Directory.CreateDirectory(Path.Join(Utilities.OperatingDirectory, "Log"));
+ }
+ }
+
///
/// moves existing configs from the root folder into a configs folder
///
diff --git a/Application/Misc/Logger.cs b/Application/Misc/Logger.cs
index 13ae7d3d7..79080c667 100644
--- a/Application/Misc/Logger.cs
+++ b/Application/Misc/Logger.cs
@@ -55,6 +55,7 @@ namespace IW4MAdmin.Application
void Write(string msg, LogType type)
{
+ return;
OnLogWriting.Wait();
string stringType = type.ToString();
diff --git a/IW4MAdmin.sln b/IW4MAdmin.sln
index 90bfe320b..b96653921 100644
--- a/IW4MAdmin.sln
+++ b/IW4MAdmin.sln
@@ -1,6 +1,6 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.26730.16
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.28803.352
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Plugins", "Plugins", "{26E8B310-269E-46D4-A612-24601F16065F}"
EndProject
diff --git a/Plugins/Stats/Helpers/StatManager.cs b/Plugins/Stats/Helpers/StatManager.cs
index 27a6b0988..5aea63a9f 100644
--- a/Plugins/Stats/Helpers/StatManager.cs
+++ b/Plugins/Stats/Helpers/StatManager.cs
@@ -20,25 +20,22 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
{
public class StatManager
{
- private ConcurrentDictionary Servers;
- private ILogger Log;
- private readonly IManager Manager;
-
+ private readonly ConcurrentDictionary _servers;
+ private readonly ILogger _log;
private readonly SemaphoreSlim OnProcessingPenalty;
private readonly SemaphoreSlim OnProcessingSensitive;
public StatManager(IManager mgr)
{
- Servers = new ConcurrentDictionary();
- Log = mgr.GetLogger(0);
- Manager = mgr;
+ _servers = new ConcurrentDictionary();
+ _log = mgr.GetLogger(0);
OnProcessingPenalty = new SemaphoreSlim(1, 1);
OnProcessingSensitive = new SemaphoreSlim(1, 1);
}
public EFClientStatistics GetClientStats(int clientId, long serverId)
{
- return Servers[serverId].PlayerStats[clientId];
+ return _servers[serverId].PlayerStats[clientId];
}
public static Expression> GetRankingFunc(long? serverId = null)
@@ -135,6 +132,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
var iqStatsInfo = (from stat in context.Set()
where clientIds.Contains(stat.ClientId)
+ where stat.Kills > 0 || stat.Deaths > 0
group stat by stat.ClientId into s
select new
{
@@ -242,7 +240,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
// check to see if the stats have ever been initialized
var serverStats = InitializeServerStats(server.ServerId);
- Servers.TryAdd(serverId, new ServerStats(server, serverStats)
+ _servers.TryAdd(serverId, new ServerStats(server, serverStats)
{
IsTeamBased = sv.Gametype != "dm"
});
@@ -250,8 +248,8 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
catch (Exception e)
{
- Log.WriteError($"{Utilities.CurrentLocalization.LocalizationIndex["PLUGIN_STATS_ERROR_ADD"]} - {e.Message}");
- Log.WriteDebug(e.GetExceptionInfo());
+ _log.WriteError($"{Utilities.CurrentLocalization.LocalizationIndex["PLUGIN_STATS_ERROR_ADD"]} - {e.Message}");
+ _log.WriteDebug(e.GetExceptionInfo());
}
}
@@ -268,18 +266,18 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
{
long serverId = await GetIdForServer(pl.CurrentServer);
- if (!Servers.ContainsKey(serverId))
+ if (!_servers.ContainsKey(serverId))
{
- Log.WriteError($"[Stats::AddPlayer] Server with id {serverId} could not be found");
+ _log.WriteError($"[Stats::AddPlayer] Server with id {serverId} could not be found");
return null;
}
- var playerStats = Servers[serverId].PlayerStats;
- var detectionStats = Servers[serverId].PlayerDetections;
+ var playerStats = _servers[serverId].PlayerStats;
+ var detectionStats = _servers[serverId].PlayerDetections;
if (playerStats.ContainsKey(pl.ClientId))
{
- Log.WriteWarning($"Duplicate ClientId in stats {pl.ClientId}");
+ _log.WriteWarning($"Duplicate ClientId in stats {pl.ClientId}");
return playerStats[pl.ClientId];
}
@@ -321,7 +319,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
if (!playerStats.TryAdd(clientStats.ClientId, clientStats))
{
- Log.WriteWarning("Adding new client to stats failed");
+ _log.WriteWarning("Adding new client to stats failed");
}
}
@@ -329,7 +327,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
{
if (!playerStats.TryAdd(clientStats.ClientId, clientStats))
{
- Log.WriteWarning("Adding pre-existing client to stats failed");
+ _log.WriteWarning("Adding pre-existing client to stats failed");
}
}
@@ -366,9 +364,9 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
clientStats.SessionScore = pl.Score;
clientStats.LastScore = pl.Score;
- if (!detectionStats.TryAdd(pl.ClientId, new Cheat.Detection(Log, clientStats)))
+ if (!detectionStats.TryAdd(pl.ClientId, new Cheat.Detection(_log, clientStats)))
{
- Log.WriteWarning("Could not add client to detection");
+ _log.WriteWarning("Could not add client to detection");
}
pl.CurrentServer.Logger.WriteInfo($"Adding {pl} to stats");
@@ -379,8 +377,8 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
catch (Exception ex)
{
- Log.WriteWarning("Could not add client to stats");
- Log.WriteDebug(ex.GetExceptionInfo());
+ _log.WriteWarning("Could not add client to stats");
+ _log.WriteDebug(ex.GetExceptionInfo());
}
finally
@@ -401,9 +399,9 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
pl.CurrentServer.Logger.WriteInfo($"Removing {pl} from stats");
long serverId = await GetIdForServer(pl.CurrentServer);
- var playerStats = Servers[serverId].PlayerStats;
- var detectionStats = Servers[serverId].PlayerDetections;
- var serverStats = Servers[serverId].ServerStatistics;
+ var playerStats = _servers[serverId].PlayerStats;
+ var detectionStats = _servers[serverId].PlayerDetections;
+ var serverStats = _servers[serverId].ServerStatistics;
if (!playerStats.ContainsKey(pl.ClientId))
{
@@ -473,8 +471,8 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
catch (FormatException)
{
- Log.WriteWarning("Could not parse kill or death origin or viewangle vectors");
- Log.WriteDebug($"Kill - {killOrigin} Death - {deathOrigin} ViewAngle - {viewAngles}");
+ _log.WriteWarning("Could not parse kill or death origin or viewangle vectors");
+ _log.WriteDebug($"Kill - {killOrigin} Death - {deathOrigin} ViewAngle - {viewAngles}");
await AddStandardKill(attacker, victim);
return;
}
@@ -491,7 +489,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
catch (FormatException)
{
- Log.WriteWarning("Could not parse snapshot angles");
+ _log.WriteWarning("Could not parse snapshot angles");
return;
}
@@ -537,13 +535,13 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
}
// incase the add player event get delayed
- if (!Servers[serverId].PlayerStats.ContainsKey(attacker.ClientId))
+ if (!_servers[serverId].PlayerStats.ContainsKey(attacker.ClientId))
{
await AddPlayer(attacker);
}
- var clientDetection = Servers[serverId].PlayerDetections[attacker.ClientId];
- var clientStats = Servers[serverId].PlayerStats[attacker.ClientId];
+ var clientDetection = _servers[serverId].PlayerDetections[attacker.ClientId];
+ var clientStats = _servers[serverId].PlayerStats[attacker.ClientId];
using (var ctx = new DatabaseContext(disableTracking: true))
{
@@ -598,8 +596,8 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
catch (Exception ex)
{
- Log.WriteError("Could not save hit or AC info");
- Log.WriteDebug(ex.GetExceptionInfo());
+ _log.WriteError("Could not save hit or AC info");
+ _log.WriteDebug(ex.GetExceptionInfo());
}
OnProcessingPenalty.Release(1);
@@ -627,7 +625,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
}
};
- await attacker.Ban(Utilities.CurrentLocalization.LocalizationIndex["PLUGIN_STATS_CHEAT_DETECTED"], penaltyClient, false).WaitAsync();
+ await attacker.Ban(Utilities.CurrentLocalization.LocalizationIndex["PLUGIN_STATS_CHEAT_DETECTED"], penaltyClient, false).WaitAsync(Utilities.DefaultCommandTimeout, attacker.CurrentServer.Manager.CancellationToken);
if (clientDetection.Tracker.HasChanges)
{
@@ -644,7 +642,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
$"{penalty.Type}-{(int)penalty.Location}-{Math.Round(penalty.Value, 2)}@{penalty.HitCount}" :
$"{penalty.Type}-{Math.Round(penalty.Value, 2)}@{penalty.HitCount}";
- await attacker.Flag(flagReason, penaltyClient).WaitAsync();
+ await attacker.Flag(flagReason, penaltyClient).WaitAsync(Utilities.DefaultCommandTimeout, attacker.CurrentServer.Manager.CancellationToken);
if (clientDetection.Tracker.HasChanges)
{
@@ -714,33 +712,33 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
long serverId = await GetIdForServer(attacker.CurrentServer);
EFClientStatistics attackerStats = null;
- if (!Servers[serverId].PlayerStats.ContainsKey(attacker.ClientId))
+ if (!_servers[serverId].PlayerStats.ContainsKey(attacker.ClientId))
{
attackerStats = await AddPlayer(attacker);
}
else
{
- attackerStats = Servers[serverId].PlayerStats[attacker.ClientId];
+ attackerStats = _servers[serverId].PlayerStats[attacker.ClientId];
}
EFClientStatistics victimStats = null;
- if (!Servers[serverId].PlayerStats.ContainsKey(victim.ClientId))
+ if (!_servers[serverId].PlayerStats.ContainsKey(victim.ClientId))
{
victimStats = await AddPlayer(victim);
}
else
{
- victimStats = Servers[serverId].PlayerStats[victim.ClientId];
+ victimStats = _servers[serverId].PlayerStats[victim.ClientId];
}
#if DEBUG
- Log.WriteDebug("Calculating standard kill");
+ _log.WriteDebug("Calculating standard kill");
#endif
// update the total stats
- Servers[serverId].ServerStatistics.TotalKills += 1;
+ _servers[serverId].ServerStatistics.TotalKills += 1;
await Sync(attacker.CurrentServer);
// this happens when the round has changed
@@ -777,14 +775,14 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
// fixme: why?
if (double.IsNaN(victimStats.SPM) || double.IsNaN(victimStats.Skill))
{
- Log.WriteDebug($"[StatManager::AddStandardKill] victim SPM/SKILL {victimStats.SPM} {victimStats.Skill}");
+ _log.WriteDebug($"[StatManager::AddStandardKill] victim SPM/SKILL {victimStats.SPM} {victimStats.Skill}");
victimStats.SPM = 0.0;
victimStats.Skill = 0.0;
}
if (double.IsNaN(attackerStats.SPM) || double.IsNaN(attackerStats.Skill))
{
- Log.WriteDebug($"[StatManager::AddStandardKill] attacker SPM/SKILL {victimStats.SPM} {victimStats.Skill}");
+ _log.WriteDebug($"[StatManager::AddStandardKill] attacker SPM/SKILL {victimStats.SPM} {victimStats.Skill}");
attackerStats.SPM = 0.0;
attackerStats.Skill = 0.0;
}
@@ -1014,7 +1012,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
attackerStats = UpdateStats(attackerStats);
// calulate elo
- if (Servers[attackerStats.ServerId].PlayerStats.Count > 1)
+ if (_servers[attackerStats.ServerId].PlayerStats.Count > 1)
{
#region DEPRECATED
/* var validAttackerLobbyRatings = Servers[attackerStats.ServerId].PlayerStats
@@ -1095,7 +1093,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
}
double killSPM = scoreDifference / timeSinceLastCalc;
- double spmMultiplier = 2.934 * Math.Pow(Servers[clientStats.ServerId].TeamCount(clientStats.Team == IW4Info.Team.Allies ? IW4Info.Team.Axis : IW4Info.Team.Allies), -0.454);
+ double spmMultiplier = 2.934 * Math.Pow(_servers[clientStats.ServerId].TeamCount(clientStats.Team == IW4Info.Team.Allies ? IW4Info.Team.Axis : IW4Info.Team.Allies), -0.454);
killSPM *= Math.Max(1, spmMultiplier);
// update this for ac tracking
@@ -1120,8 +1118,8 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
if (clientStats.SPM < 0)
{
- Log.WriteWarning("[StatManager:UpdateStats] clientStats SPM < 0");
- Log.WriteDebug($"{scoreDifference}-{clientStats.RoundScore} - {clientStats.LastScore} - {clientStats.SessionScore}");
+ _log.WriteWarning("[StatManager:UpdateStats] clientStats SPM < 0");
+ _log.WriteDebug($"{scoreDifference}-{clientStats.RoundScore} - {clientStats.LastScore} - {clientStats.SessionScore}");
clientStats.SPM = 0;
}
@@ -1131,8 +1129,8 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
// fixme: how does this happen?
if (double.IsNaN(clientStats.SPM) || double.IsNaN(clientStats.Skill))
{
- Log.WriteWarning("[StatManager::UpdateStats] clientStats SPM/Skill NaN");
- Log.WriteDebug($"{killSPM}-{KDRWeight}-{totalPlayTime}-{SPMAgainstPlayWeight}-{clientStats.SPM}-{clientStats.Skill}-{scoreDifference}");
+ _log.WriteWarning("[StatManager::UpdateStats] clientStats SPM/Skill NaN");
+ _log.WriteDebug($"{killSPM}-{KDRWeight}-{totalPlayTime}-{SPMAgainstPlayWeight}-{clientStats.SPM}-{clientStats.Skill}-{scoreDifference}");
clientStats.SPM = 0;
clientStats.Skill = 0;
}
@@ -1154,7 +1152,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
if (serverStats == null)
{
- Log.WriteDebug($"Initializing server stats for {serverId}");
+ _log.WriteDebug($"Initializing server stats for {serverId}");
// server stats have never been generated before
serverStats = new EFServerStatistics()
{
@@ -1173,7 +1171,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
public void ResetKillstreaks(long serverId)
{
- var serverStats = Servers[serverId];
+ var serverStats = _servers[serverId];
foreach (var stat in serverStats.PlayerStats.Values)
{
@@ -1183,7 +1181,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
public void ResetStats(int clientId, long serverId)
{
- var stats = Servers[serverId].PlayerStats[clientId];
+ var stats = _servers[serverId].PlayerStats[clientId];
stats.Kills = 0;
stats.Deaths = 0;
stats.SPM = 0;
@@ -1221,10 +1219,10 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
using (var ctx = new DatabaseContext(disableTracking: true))
{
var serverSet = ctx.Set();
- serverSet.Update(Servers[serverId].Server);
+ serverSet.Update(_servers[serverId].Server);
var serverStatsSet = ctx.Set();
- serverStatsSet.Update(Servers[serverId].ServerStatistics);
+ serverStatsSet.Update(_servers[serverId].ServerStatistics);
await ctx.SaveChangesAsync();
}
@@ -1232,7 +1230,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
public void SetTeamBased(long serverId, bool isTeamBased)
{
- Servers[serverId].IsTeamBased = isTeamBased;
+ _servers[serverId].IsTeamBased = isTeamBased;
}
public static async Task GetIdForServer(Server server)
diff --git a/SharedLibraryCore/Commands/NativeCommands.cs b/SharedLibraryCore/Commands/NativeCommands.cs
index dcc3e1b53..c6faf8e14 100644
--- a/SharedLibraryCore/Commands/NativeCommands.cs
+++ b/SharedLibraryCore/Commands/NativeCommands.cs
@@ -23,7 +23,22 @@ namespace SharedLibraryCore.Commands
public override Task ExecuteAsync(GameEvent E)
{
- return Task.Run(() => { E.Owner.Manager.Stop(); });
+ E.Owner.Manager.Stop();
+ return Task.CompletedTask;
+ }
+ }
+
+ public class CRestart : Command
+ {
+ public CRestart() :
+ base("restart", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_RESTART_DESC"], "rs", EFClient.Permission.Owner, false)
+ { }
+
+ public override Task ExecuteAsync(GameEvent E)
+ {
+ E.Owner.Manager.Restart();
+ E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_RESTART_SUCCESS"]);
+ return Task.CompletedTask;
}
}
@@ -120,9 +135,18 @@ namespace SharedLibraryCore.Commands
public override async Task ExecuteAsync(GameEvent E)
{
- var _ = !(await E.Target.Kick(E.Data, E.Origin).WaitAsync()).Failed ?
- E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_KICK_SUCCESS"].FormatExt(E.Target.Name)) :
- E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_KICK_FAIL"].FormatExt(E.Target.Name));
+ switch ((await E.Target.Kick(E.Data, E.Origin).WaitAsync(Utilities.DefaultCommandTimeout, E.Owner.Manager.CancellationToken)).FailReason)
+ {
+ case GameEvent.EventFailReason.None:
+ E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_KICK_SUCCESS"].FormatExt(E.Target.Name));
+ break;
+ case GameEvent.EventFailReason.Exception:
+ E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_COMMAND_INGAME"]);
+ break;
+ default:
+ E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_KICK_FAIL"].FormatExt(E.Target.Name));
+ break;
+ }
}
}
@@ -186,9 +210,18 @@ namespace SharedLibraryCore.Commands
else
{
- var _ = !(await E.Target.TempBan(tempbanReason, length, E.Origin).WaitAsync()).Failed ?
- E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_TEMPBAN_SUCCESS"].FormatExt(E.Target, length.TimeSpanText())) :
- E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_TEMPBAN_FAIL"].FormatExt(E.Target.Name));
+ switch ((await E.Target.TempBan(tempbanReason, length, E.Origin).WaitAsync(Utilities.DefaultCommandTimeout, E.Owner.Manager.CancellationToken)).FailReason)
+ {
+ case GameEvent.EventFailReason.None:
+ E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_TEMPBAN_SUCCESS"].FormatExt(E.Target, length.TimeSpanText()));
+ break;
+ case GameEvent.EventFailReason.Exception:
+ E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_COMMAND_INGAME"]);
+ break;
+ default:
+ E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_TEMPBAN_FAIL"].FormatExt(E.Target.Name));
+ break;
+ }
}
}
}
@@ -214,9 +247,18 @@ namespace SharedLibraryCore.Commands
public override async Task ExecuteAsync(GameEvent E)
{
- var _ = !(await E.Target.Ban(E.Data, E.Origin, false).WaitAsync()).Failed ?
- E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_BAN_SUCCESS"].FormatExt(E.Target.Name)) :
+ switch ((await E.Target.Ban(E.Data, E.Origin, false).WaitAsync(Utilities.DefaultCommandTimeout, E.Owner.Manager.CancellationToken)).FailReason)
+ {
+ case GameEvent.EventFailReason.None:
+ E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_BAN_SUCCESS"].FormatExt(E.Target.Name));
+ break;
+ case GameEvent.EventFailReason.Exception:
+ E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_COMMAND_INGAME"]);
+ break;
+ default:
E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_BAN_FAIL"].FormatExt(E.Target.Name));
+ break;
+ }
}
}
@@ -240,12 +282,21 @@ namespace SharedLibraryCore.Commands
public override async Task ExecuteAsync(GameEvent E)
{
+ // todo: don't do the lookup here
var penalties = await E.Owner.Manager.GetPenaltyService().GetActivePenaltiesAsync(E.Target.AliasLinkId);
if (penalties.Where(p => p.Type == Penalty.PenaltyType.Ban || p.Type == Penalty.PenaltyType.TempBan).FirstOrDefault() != null)
{
- await E.Target.Unban(E.Data, E.Origin).WaitAsync();
- E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_UNBAN_SUCCESS"].FormatExt(E.Target));
+ switch ((await E.Target.Unban(E.Data, E.Origin).WaitAsync(Utilities.DefaultCommandTimeout, E.Owner.Manager.CancellationToken)).FailReason)
+ {
+ case GameEvent.EventFailReason.None:
+ E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_UNBAN_SUCCESS"].FormatExt(E.Target));
+ break;
+ default:
+ E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_COMMAND_INGAME"]);
+ break;
+ }
}
+
else
{
E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_UNBAN_FAIL"].FormatExt(E.Target));
@@ -587,12 +638,13 @@ namespace SharedLibraryCore.Commands
if (m.Name.ToLower() == newMap || m.Alias.ToLower() == newMap)
{
E.Owner.Broadcast(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_MAP_SUCCESS"].FormatExt(m.Alias));
- await Task.Delay(5000);
+ await Task.Delay((int)(Utilities.DefaultCommandTimeout.TotalMilliseconds / 2.0));
await E.Owner.LoadMap(m.Name);
return;
}
}
+ // todo: this can be moved into a single statement
E.Owner.Broadcast(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_MAP_UKN"].FormatExt(newMap));
await Task.Delay(5000);
await E.Owner.LoadMap(newMap);
@@ -720,27 +772,23 @@ namespace SharedLibraryCore.Commands
})
{ }
- public override Task ExecuteAsync(GameEvent E)
+ public override async Task ExecuteAsync(GameEvent E)
{
- var flagEvent = E.Target.Flag(E.Data, E.Origin);
-
- if (E.FailReason == GameEvent.EventFailReason.Permission)
+ switch ((await E.Target.Flag(E.Data, E.Origin).WaitAsync(Utilities.DefaultCommandTimeout, E.Owner.Manager.CancellationToken)).FailReason)
{
- E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_FLAG_FAIL"].FormatExt(E.Target.Name));
+ case GameEvent.EventFailReason.Permission:
+ E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_FLAG_FAIL"].FormatExt(E.Target.Name));
+ break;
+ case GameEvent.EventFailReason.Invalid:
+ E.Origin.Tell($"{Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_FLAG_ALREADYFLAGGED"]}");
+ break;
+ case GameEvent.EventFailReason.None:
+ E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_FLAG_SUCCESS"].FormatExt(E.Target.Name));
+ break;
+ default:
+ E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_COMMAND_INGAME"]);
+ break;
}
-
- else if (E.FailReason == GameEvent.EventFailReason.Invalid)
- {
- E.Origin.Tell($"{Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_FLAG_ALREADYFLAGGED"]}");
- }
-
- else
- {
- E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_FLAG_SUCCESS"].FormatExt(E.Target.Name));
- }
-
- return Task.CompletedTask;
-
}
}
@@ -757,27 +805,23 @@ namespace SharedLibraryCore.Commands
})
{ }
- public override Task ExecuteAsync(GameEvent E)
+ public override async Task ExecuteAsync(GameEvent E)
{
- var unflagEvent = E.Target.Unflag(E.Data, E.Origin);
-
- if (unflagEvent.FailReason == GameEvent.EventFailReason.Permission)
+ switch ((await E.Target.Unflag(E.Data, E.Origin).WaitAsync(Utilities.DefaultCommandTimeout, E.Owner.Manager.CancellationToken)).FailReason)
{
- E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_UNFLAG_FAIL"].FormatExt(E.Target.Name));
+ case GameEvent.EventFailReason.None:
+ E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_FLAG_UNFLAG"].FormatExt(E.Target.Name));
+ break;
+ case GameEvent.EventFailReason.Permission:
+ E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_UNFLAG_FAIL"].FormatExt(E.Target.Name));
+ break;
+ case GameEvent.EventFailReason.Invalid:
+ E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_UNFLAG_NOTFLAGGED"]);
+ break;
+ default:
+ E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_COMMAND_INGAME"]);
+ break;
}
-
- else if (unflagEvent.FailReason == GameEvent.EventFailReason.Invalid)
- {
- E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_UNFLAG_NOTFLAGGED"]);
- }
-
- else
- {
- E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_FLAG_UNFLAG"].FormatExt(E.Target.Name));
- }
-
- return Task.CompletedTask;
- // todo: update immediately?
}
}
@@ -808,46 +852,30 @@ namespace SharedLibraryCore.Commands
return;
}
- var reportEvent = commandEvent.Target.Report(commandEvent.Data, commandEvent.Origin);
+ bool success = false;
- if (reportEvent.FailReason == GameEvent.EventFailReason.Permission)
+ switch ((await commandEvent.Target.Report(commandEvent.Data, commandEvent.Origin).WaitAsync(Utilities.DefaultCommandTimeout, commandEvent.Owner.Manager.CancellationToken)).FailReason)
{
- commandEvent.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_REPORT_FAIL"].FormatExt(commandEvent.Target.Name));
+ case GameEvent.EventFailReason.None:
+ commandEvent.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_REPORT_SUCCESS"]);
+ success = true;
+ break;
+ case GameEvent.EventFailReason.Exception:
+ commandEvent.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_REPORT_FAIL_DUPLICATE"]);
+ break;
+ case GameEvent.EventFailReason.Permission:
+ commandEvent.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_REPORT_FAIL"].FormatExt(commandEvent.Target.Name));
+ break;
+ case GameEvent.EventFailReason.Invalid:
+ commandEvent.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_REPORT_FAIL_SELF"]);
+ break;
+ case GameEvent.EventFailReason.Throttle:
+ commandEvent.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_REPORT_FAIL_TOOMANY"]);
+ break;
}
- else if (reportEvent.FailReason == GameEvent.EventFailReason.Invalid)
+ if (success)
{
- commandEvent.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_REPORT_FAIL_SELF"]);
- }
-
- else if (reportEvent.FailReason == GameEvent.EventFailReason.Throttle)
- {
- commandEvent.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_REPORT_FAIL_TOOMANY"]);
- }
-
- else if (reportEvent.Failed)
- {
- commandEvent.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_REPORT_FAIL_DUPLICATE"]);
- }
-
- else
- {
- // todo: move into server
- Penalty newReport = new Penalty()
- {
- Type = Penalty.PenaltyType.Report,
- Expires = DateTime.UtcNow,
- Offender = commandEvent.Target,
- Offense = commandEvent.Data,
- Punisher = commandEvent.Origin,
- Active = true,
- When = DateTime.UtcNow,
- Link = commandEvent.Target.AliasLink
- };
-
- await commandEvent.Owner.Manager.GetPenaltyService().Create(newReport);
-
- commandEvent.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_REPORT_SUCCESS"]);
commandEvent.Owner.ToAdmins(String.Format("^5{0}^7->^1{1}^7: {2}", commandEvent.Origin.Name, commandEvent.Target.Name, commandEvent.Data));
}
}
@@ -1118,10 +1146,6 @@ namespace SharedLibraryCore.Commands
E.Origin.Password = hashedPassword[0];
E.Origin.PasswordSalt = hashedPassword[1];
- // update the password for the client in privileged
- //E.Owner.Manager.PrivilegedClients[E.Origin.ClientId].Password = hashedPassword[0];
- //E.Owner.Manager.PrivilegedClients[E.Origin.ClientId].PasswordSalt = hashedPassword[1];
-
await E.Owner.Manager.GetClientService().Update(E.Origin);
E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_PASSWORD_SUCCESS"]);
}
diff --git a/SharedLibraryCore/Database/DatabaseContext.cs b/SharedLibraryCore/Database/DatabaseContext.cs
index b9d9b10ff..bf644876b 100644
--- a/SharedLibraryCore/Database/DatabaseContext.cs
+++ b/SharedLibraryCore/Database/DatabaseContext.cs
@@ -29,7 +29,7 @@ namespace SharedLibraryCore.Database
{
#if DEBUG == true
activeContextCount++;
- Console.WriteLine($"Initialized DB Context #{activeContextCount}");
+ //Console.WriteLine($"Initialized DB Context #{activeContextCount}");
#endif
}
@@ -37,7 +37,7 @@ namespace SharedLibraryCore.Database
{
#if DEBUG == true
activeContextCount++;
- Console.WriteLine($"Initialized DB Context #{activeContextCount}");
+ //Console.WriteLine($"Initialized DB Context #{activeContextCount}");
#endif
}
@@ -45,7 +45,7 @@ namespace SharedLibraryCore.Database
{
#if DEBUG == true
- Console.WriteLine($"Disposed DB Context #{activeContextCount}");
+ //Console.WriteLine($"Disposed DB Context #{activeContextCount}");
activeContextCount--;
#endif
}
diff --git a/SharedLibraryCore/Events/GameEvent.cs b/SharedLibraryCore/Events/GameEvent.cs
index a77eb427a..9cafac0a6 100644
--- a/SharedLibraryCore/Events/GameEvent.cs
+++ b/SharedLibraryCore/Events/GameEvent.cs
@@ -212,11 +212,11 @@ namespace SharedLibraryCore
/// asynchronously wait for GameEvent to be processed
///
/// waitable task
- public Task WaitAsync(int timeOut = int.MaxValue)
+ public Task WaitAsync(TimeSpan timeSpan, CancellationToken token)
{
return Task.Run(() =>
{
- OnProcessed.Wait(timeOut);
+ OnProcessed.Wait(timeSpan, token);
return this;
});
}
diff --git a/SharedLibraryCore/Interfaces/IManager.cs b/SharedLibraryCore/Interfaces/IManager.cs
index 0f28d960d..5f2e1a4fb 100644
--- a/SharedLibraryCore/Interfaces/IManager.cs
+++ b/SharedLibraryCore/Interfaces/IManager.cs
@@ -7,14 +7,16 @@ using SharedLibraryCore.Configuration;
using System.Reflection;
using SharedLibraryCore.Database.Models;
using System.Collections.Concurrent;
+using System.Threading;
namespace SharedLibraryCore.Interfaces
{
public interface IManager
{
Task Init();
- void Start();
+ Task Start();
void Stop();
+ void Restart();
ILogger GetLogger(long serverId);
IList GetServers();
IList GetCommands();
@@ -29,11 +31,6 @@ namespace SharedLibraryCore.Interfaces
///
/// EventHandler for the manager
IEventHandler GetEventHandler();
- ///
- /// Signal to the manager that event(s) needs to be processed
- ///
- void SetHasEvent();
- bool ShutdownRequested();
IList GetPluginAssemblies();
///
/// provides a page list to add and remove from
@@ -47,5 +44,7 @@ namespace SharedLibraryCore.Interfaces
string Version { get;}
ITokenAuthentication TokenAuthenticator { get; }
string ExternalIPAddress { get; }
+ CancellationToken CancellationToken { get; }
+ bool IsRestartRequested { get; }
}
}
diff --git a/SharedLibraryCore/Objects/EFClient.cs b/SharedLibraryCore/Objects/EFClient.cs
index e1203aca6..562657302 100644
--- a/SharedLibraryCore/Objects/EFClient.cs
+++ b/SharedLibraryCore/Objects/EFClient.cs
@@ -546,6 +546,7 @@ namespace SharedLibraryCore.Database.Models
profileBan = (await CurrentServer.Manager
.GetPenaltyService()
.GetActivePenaltiesAsync(AliasLinkId))
+ .OrderByDescending(_penalty => _penalty.When)
.FirstOrDefault(_penalty => _penalty.Type == Penalty.PenaltyType.Ban);
CurrentServer.Logger.WriteWarning($"Client {this} is GUID banned, but no previous penalty exists for their ban");
@@ -596,18 +597,6 @@ namespace SharedLibraryCore.Database.Models
// we want to get any penalties that are tied to their IP or AliasLink (but not necessarily their GUID)
var activePenalties = await CurrentServer.Manager.GetPenaltyService().GetActivePenaltiesAsync(AliasLinkId, ipAddress);
- #region CLIENT_LINKED_TEMPBAN
- var tempBan = activePenalties.FirstOrDefault(_penalty => _penalty.Type == Penalty.PenaltyType.TempBan);
-
- // they have an active tempban tied to their AliasLink
- if (tempBan != null)
- {
- CurrentServer.Logger.WriteDebug($"Tempbanning {this} because their AliasLink is temporarily banned, but they are not");
- TempBan(tempBan.Offense, DateTime.UtcNow - (tempBan.Expires ?? DateTime.UtcNow), autoKickClient);
- return false;
- }
- #endregion
-
#region CLIENT_LINKED_BAN
var currentBan = activePenalties.FirstOrDefault(p => p.Type == Penalty.PenaltyType.Ban);
@@ -642,6 +631,20 @@ namespace SharedLibraryCore.Database.Models
}
#endregion
+ #region CLIENT_LINKED_TEMPBAN
+ var tempBan = activePenalties
+ .OrderByDescending(_penalty => _penalty.When)
+ .FirstOrDefault(_penalty => _penalty.Type == Penalty.PenaltyType.TempBan);
+
+ // they have an active tempban tied to their AliasLink
+ if (tempBan != null)
+ {
+ CurrentServer.Logger.WriteDebug($"Tempbanning {this} because their AliasLink is temporarily banned, but they are not");
+ TempBan(tempBan.Offense, DateTime.UtcNow - (tempBan.Expires ?? DateTime.UtcNow), autoKickClient);
+ return false;
+ }
+ #endregion
+
#region CLIENT_LINKED_FLAG
if (Level != Permission.Flagged)
{
diff --git a/SharedLibraryCore/ScriptPlugin.cs b/SharedLibraryCore/ScriptPlugin.cs
index ed5bf3a1b..aecebd39b 100644
--- a/SharedLibraryCore/ScriptPlugin.cs
+++ b/SharedLibraryCore/ScriptPlugin.cs
@@ -42,7 +42,7 @@ namespace SharedLibraryCore
}
catch (Exception ex)
{
- Manager.GetLogger(0).WriteError($"{Utilities.CurrentLocalization.LocalizationIndex["PLUGIN_IMPORTER_ERROR"]} {Name}");
+ Manager.GetLogger(0).WriteError(Utilities.CurrentLocalization.LocalizationIndex["PLUGIN_IMPORTER_ERROR"].FormatExt(Name));
Manager.GetLogger(0).WriteDebug(ex.Message);
}
}
diff --git a/SharedLibraryCore/Server.cs b/SharedLibraryCore/Server.cs
index 3bb26ba58..dfc0f4ca9 100644
--- a/SharedLibraryCore/Server.cs
+++ b/SharedLibraryCore/Server.cs
@@ -23,10 +23,10 @@ namespace SharedLibraryCore
IW4 = 2,
IW5 = 3,
IW6 = 4,
- T4 = 5,
- T5 = 6,
- T6 = 7,
- T7 = 8
+ T4 = 5,
+ T5 = 6,
+ T6 = 7,
+ T7 = 8
}
public Server(IManager mgr, ServerConfiguration config)
@@ -159,14 +159,16 @@ namespace SharedLibraryCore
if (Target.Level == EFClient.Permission.Console)
{
- Console.ForegroundColor = ConsoleColor.Cyan;
+ Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine(Message.StripColors());
Console.ForegroundColor = ConsoleColor.Gray;
}
// prevent this from queueing up too many command responses
if (CommandResult.Count > 15)
+ {
CommandResult.RemoveAt(0);
+ }
// it was a remote command so we need to add it to the command result queue
if (Target.ClientNumber < 0)
diff --git a/SharedLibraryCore/Services/ClientService.cs b/SharedLibraryCore/Services/ClientService.cs
index e0f56ca64..e042ba5a0 100644
--- a/SharedLibraryCore/Services/ClientService.cs
+++ b/SharedLibraryCore/Services/ClientService.cs
@@ -447,8 +447,6 @@ namespace SharedLibraryCore.Services
return new List();
}
- identifier = identifier.ToLower();
-
using (var context = new DatabaseContext(disableTracking: true))
{
long? networkId = null;
@@ -472,7 +470,7 @@ namespace SharedLibraryCore.Services
// todo maybe not make it start with wildcard?
else
{
- iqLinkIds = iqLinkIds.Where(_alias => EF.Functions.Like(_alias.Name, $"%{identifier}%"));
+ iqLinkIds = iqLinkIds.Where(_alias => EF.Functions.Like(_alias.Name.ToLower(), $"%{identifier.ToLower()}%"));
}
var linkIds = await iqLinkIds
diff --git a/SharedLibraryCore/Utilities.cs b/SharedLibraryCore/Utilities.cs
index dfffc0ff5..65b9e30f7 100644
--- a/SharedLibraryCore/Utilities.cs
+++ b/SharedLibraryCore/Utilities.cs
@@ -30,6 +30,8 @@ namespace SharedLibraryCore
#endif
public static Encoding EncodingType;
public static Localization.Layout CurrentLocalization = new Localization.Layout(new Dictionary());
+ public static TimeSpan DefaultCommandTimeout = new TimeSpan(0, 0, 10);
+
public static EFClient IW4MAdminClient(Server server = null)
{
return new EFClient()
@@ -320,7 +322,7 @@ namespace SharedLibraryCore
if (Elapsed.TotalSeconds < 30)
{
- return CurrentLocalization.LocalizationIndex["GLOBAL_TIME_JUSTNOW"];
+ return CurrentLocalization.LocalizationIndex["GLOBAL_TIME_JUSTNOW"] + ago;
}
if (Elapsed.TotalMinutes < 120)
{
@@ -783,6 +785,11 @@ namespace SharedLibraryCore
}
}
+ ///
+ /// Determines if the given message is a quick message
+ ///
+ ///
+ /// true if the
public static bool IsQuickMessage(this string message)
{
return Regex.IsMatch(message, @"^\u0014(?:[A-Z]|_)+$");
diff --git a/WebfrontCore/Controllers/ConsoleController.cs b/WebfrontCore/Controllers/ConsoleController.cs
index e85dacd0b..ca8b5c85a 100644
--- a/WebfrontCore/Controllers/ConsoleController.cs
+++ b/WebfrontCore/Controllers/ConsoleController.cs
@@ -53,7 +53,7 @@ namespace WebfrontCore.Controllers
Manager.GetEventHandler().AddEvent(remoteEvent);
List response;
// wait for the event to process
- if (!(await remoteEvent.WaitAsync(60 * 1000)).Failed)
+ if (!(await remoteEvent.WaitAsync(Utilities.DefaultCommandTimeout, server.Manager.CancellationToken)).Failed)
{
response = server.CommandResult.Where(c => c.ClientId == client.ClientId).ToList();
diff --git a/WebfrontCore/Program.cs b/WebfrontCore/Program.cs
index cb093725c..8b5fd970a 100644
--- a/WebfrontCore/Program.cs
+++ b/WebfrontCore/Program.cs
@@ -1,4 +1,6 @@
using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using SharedLibraryCore.Interfaces;
@@ -9,18 +11,18 @@ namespace WebfrontCore
{
public static IManager Manager;
- static void Main(string[] args)
+ static void Main()
{
throw new System.Exception("Webfront core cannot be run as a standalone application");
}
- public static void Init(IManager mgr)
+ public static Task Init(IManager mgr, CancellationToken cancellationToken)
{
Manager = mgr;
- BuildWebHost().Run();
+ return BuildWebHost().RunAsync(cancellationToken);
}
- public static IWebHost BuildWebHost()
+ private static IWebHost BuildWebHost()
{
var config = new ConfigurationBuilder()
.AddEnvironmentVariables()