fix aggregate issue with KDR on global top stats
refactor some of the main application code to have a cleaner code flow add enviroment flag to opt out of .net core telemetry in start script fixed "a moment" missing the "ago" fixed case sensitive client searches on postgresql clean up command code flow Add missing map "mp_cairo" to default settings
This commit is contained in:
parent
43c4d4af38
commit
1dc0f5a240
@ -6,7 +6,7 @@
|
||||
<RuntimeFrameworkVersion>2.2.2</RuntimeFrameworkVersion>
|
||||
<MvcRazorExcludeRefAssembliesFromPublish>false</MvcRazorExcludeRefAssembliesFromPublish>
|
||||
<PackageId>RaidMax.IW4MAdmin.Application</PackageId>
|
||||
<Version>2.2.7.1</Version>
|
||||
<Version>2.2.7.2</Version>
|
||||
<Authors>RaidMax</Authors>
|
||||
<Company>Forever None</Company>
|
||||
<Product>IW4MAdmin</Product>
|
||||
@ -32,8 +32,8 @@
|
||||
<PropertyGroup>
|
||||
<ServerGarbageCollection>true</ServerGarbageCollection>
|
||||
<TieredCompilation>true</TieredCompilation>
|
||||
<AssemblyVersion>2.2.7.1</AssemblyVersion>
|
||||
<FileVersion>2.2.7.1</FileVersion>
|
||||
<AssemblyVersion>2.2.7.2</AssemblyVersion>
|
||||
<FileVersion>2.2.7.2</FileVersion>
|
||||
<LangVersion>7.1</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
@ -47,12 +47,6 @@
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="DefaultSettings.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Update="Microsoft.NETCore.App" Version="2.2.2" />
|
||||
</ItemGroup>
|
||||
|
@ -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<Server> _servers;
|
||||
private ConcurrentBag<Server> _servers;
|
||||
public List<Server> 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<IRConParser> AdditionalRConParsers { get; }
|
||||
public IList<IEventParser> 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<AsyncStatus> TaskStatuses;
|
||||
List<Command> Commands;
|
||||
@ -52,16 +54,16 @@ namespace IW4MAdmin.Application
|
||||
readonly PenaltyService PenaltySvc;
|
||||
public BaseConfigurationHandler<ApplicationConfiguration> ConfigHandler;
|
||||
GameEventHandler Handler;
|
||||
ManualResetEventSlim OnQuit;
|
||||
readonly IPageList PageList;
|
||||
readonly SemaphoreSlim ProcessingEvent = new SemaphoreSlim(1, 1);
|
||||
readonly Dictionary<long, ILogger> Loggers = new Dictionary<long, ILogger>();
|
||||
private readonly MetaService _metaService;
|
||||
private readonly TimeSpan _throttleTimeout = new TimeSpan(0, 1, 0);
|
||||
private readonly CancellationTokenSource _tokenSource;
|
||||
|
||||
private ApplicationManager()
|
||||
{
|
||||
_servers = new List<Server>();
|
||||
_servers = new ConcurrentBag<Server>();
|
||||
Commands = new List<Command>();
|
||||
TaskStatuses = new List<AsyncStatus>();
|
||||
MessageTokens = new List<MessageToken>();
|
||||
@ -70,7 +72,6 @@ namespace IW4MAdmin.Application
|
||||
PenaltySvc = new PenaltyService();
|
||||
ConfigHandler = new BaseConfigurationHandler<ApplicationConfiguration>("IW4MAdminSettings");
|
||||
StartTime = DateTime.UtcNow;
|
||||
OnQuit = new ManualResetEventSlim();
|
||||
PageList = new PageList();
|
||||
AdditionalEventParsers = new List<IEventParser>();
|
||||
AdditionalRConParsers = new List<IRConParser>();
|
||||
@ -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<long, Task>();
|
||||
|
||||
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; }
|
||||
@ -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<Assembly> GetPluginAssemblies()
|
||||
{
|
||||
return SharedLibraryCore.Plugins.PluginImporter.PluginAssemblies.Union(SharedLibraryCore.Plugins.PluginImporter.Assemblies).ToList();
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
/// <summary>
|
||||
/// entrypoint of the application
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// event callback executed when the control + c combination is detected
|
||||
/// gracefully stops the server manager and waits for all tasks to finish
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private static async void OnCancelKey(object sender, ConsoleCancelEventArgs e)
|
||||
{
|
||||
ServerManager?.Stop();
|
||||
await ApplicationTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// task that initializes application and starts the application monitoring and runtime tasks
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
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)
|
||||
/// <summary>
|
||||
/// runs the core application tasks
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
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()
|
||||
/// <summary>
|
||||
/// checks for latest version of the application
|
||||
/// notifies user if an update is available
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// reads input from the console and executes entered commands on the default server
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
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('>');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,27 @@ namespace IW4MAdmin.Application.Migration
|
||||
/// </summary>
|
||||
class ConfigurationMigration
|
||||
{
|
||||
/// <summary>
|
||||
/// ensures required directories are created
|
||||
/// </summary>
|
||||
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"));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// moves existing configs from the root folder into a configs folder
|
||||
/// </summary>
|
||||
|
@ -55,6 +55,7 @@ namespace IW4MAdmin.Application
|
||||
|
||||
void Write(string msg, LogType type)
|
||||
{
|
||||
return;
|
||||
OnLogWriting.Wait();
|
||||
|
||||
string stringType = type.ToString();
|
||||
|
@ -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
|
||||
|
@ -20,25 +20,22 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
||||
{
|
||||
public class StatManager
|
||||
{
|
||||
private ConcurrentDictionary<long, ServerStats> Servers;
|
||||
private ILogger Log;
|
||||
private readonly IManager Manager;
|
||||
|
||||
private readonly ConcurrentDictionary<long, ServerStats> _servers;
|
||||
private readonly ILogger _log;
|
||||
private readonly SemaphoreSlim OnProcessingPenalty;
|
||||
private readonly SemaphoreSlim OnProcessingSensitive;
|
||||
|
||||
public StatManager(IManager mgr)
|
||||
{
|
||||
Servers = new ConcurrentDictionary<long, ServerStats>();
|
||||
Log = mgr.GetLogger(0);
|
||||
Manager = mgr;
|
||||
_servers = new ConcurrentDictionary<long, ServerStats>();
|
||||
_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<Func<EFRating, bool>> GetRankingFunc(long? serverId = null)
|
||||
@ -135,6 +132,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
||||
|
||||
var iqStatsInfo = (from stat in context.Set<EFClientStatistics>()
|
||||
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<EFServer>();
|
||||
serverSet.Update(Servers[serverId].Server);
|
||||
serverSet.Update(_servers[serverId].Server);
|
||||
|
||||
var serverStatsSet = ctx.Set<EFServerStatistics>();
|
||||
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<long> GetIdForServer(Server server)
|
||||
|
@ -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"]);
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -212,11 +212,11 @@ namespace SharedLibraryCore
|
||||
/// asynchronously wait for GameEvent to be processed
|
||||
/// </summary>
|
||||
/// <returns>waitable task </returns>
|
||||
public Task<GameEvent> WaitAsync(int timeOut = int.MaxValue)
|
||||
public Task<GameEvent> WaitAsync(TimeSpan timeSpan, CancellationToken token)
|
||||
{
|
||||
return Task.Run(() =>
|
||||
{
|
||||
OnProcessed.Wait(timeOut);
|
||||
OnProcessed.Wait(timeSpan, token);
|
||||
return this;
|
||||
});
|
||||
}
|
||||
|
@ -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<Server> GetServers();
|
||||
IList<Command> GetCommands();
|
||||
@ -29,11 +31,6 @@ namespace SharedLibraryCore.Interfaces
|
||||
/// </summary>
|
||||
/// <returns>EventHandler for the manager</returns>
|
||||
IEventHandler GetEventHandler();
|
||||
/// <summary>
|
||||
/// Signal to the manager that event(s) needs to be processed
|
||||
/// </summary>
|
||||
void SetHasEvent();
|
||||
bool ShutdownRequested();
|
||||
IList<Assembly> GetPluginAssemblies();
|
||||
/// <summary>
|
||||
/// 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; }
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -447,8 +447,6 @@ namespace SharedLibraryCore.Services
|
||||
return new List<PlayerInfo>();
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -30,6 +30,8 @@ namespace SharedLibraryCore
|
||||
#endif
|
||||
public static Encoding EncodingType;
|
||||
public static Localization.Layout CurrentLocalization = new Localization.Layout(new Dictionary<string, string>());
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the given message is a quick message
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <returns>true if the </returns>
|
||||
public static bool IsQuickMessage(this string message)
|
||||
{
|
||||
return Regex.IsMatch(message, @"^\u0014(?:[A-Z]|_)+$");
|
||||
|
@ -53,7 +53,7 @@ namespace WebfrontCore.Controllers
|
||||
Manager.GetEventHandler().AddEvent(remoteEvent);
|
||||
List<CommandResponseInfo> 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();
|
||||
|
||||
|
@ -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()
|
||||
|
Loading…
Reference in New Issue
Block a user