lots of fixes :)
This commit is contained in:
parent
9ff7f39e8d
commit
e964013700
@ -21,7 +21,7 @@ namespace IW4MAdmin.Application.EventParsers
|
|||||||
{
|
{
|
||||||
return new GameEvent()
|
return new GameEvent()
|
||||||
{
|
{
|
||||||
Type = GameEvent.EventType.Script,
|
Type = GameEvent.EventType.Kill,
|
||||||
Data = logLine,
|
Data = logLine,
|
||||||
Origin = server.GetPlayersAsList().First(c => c.ClientNumber == Utilities.ClientIdFromString(lineSplit, 6)),
|
Origin = server.GetPlayersAsList().First(c => c.ClientNumber == Utilities.ClientIdFromString(lineSplit, 6)),
|
||||||
Target = server.GetPlayersAsList().First(c => c.ClientNumber == Utilities.ClientIdFromString(lineSplit, 2)),
|
Target = server.GetPlayersAsList().First(c => c.ClientNumber == Utilities.ClientIdFromString(lineSplit, 2)),
|
||||||
@ -32,13 +32,27 @@ namespace IW4MAdmin.Application.EventParsers
|
|||||||
|
|
||||||
if (cleanedEventLine == "say" || cleanedEventLine == "sayteam")
|
if (cleanedEventLine == "say" || cleanedEventLine == "sayteam")
|
||||||
{
|
{
|
||||||
|
string message = lineSplit[4].Replace("\x15", "");
|
||||||
|
|
||||||
|
if (message[0] == '!' || message[1] == '@')
|
||||||
|
{
|
||||||
|
return new GameEvent()
|
||||||
|
{
|
||||||
|
Type = GameEvent.EventType.Command,
|
||||||
|
Data = message,
|
||||||
|
Origin = server.GetPlayersAsList().First(c => c.ClientNumber == Utilities.ClientIdFromString(lineSplit, 2)),
|
||||||
|
Owner = server,
|
||||||
|
Message = message
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return new GameEvent()
|
return new GameEvent()
|
||||||
{
|
{
|
||||||
Type = GameEvent.EventType.Say,
|
Type = GameEvent.EventType.Say,
|
||||||
Data = lineSplit[4].Replace("\x15", ""),
|
Data = message,
|
||||||
Origin = server.GetPlayersAsList().First(c => c.ClientNumber == Utilities.ClientIdFromString(lineSplit, 2)),
|
Origin = server.GetPlayersAsList().First(c => c.ClientNumber == Utilities.ClientIdFromString(lineSplit, 2)),
|
||||||
Owner = server,
|
Owner = server,
|
||||||
Message = lineSplit[4].Replace("\x15", "")
|
Message = message
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,7 +60,7 @@ namespace IW4MAdmin.Application.EventParsers
|
|||||||
{
|
{
|
||||||
return new GameEvent()
|
return new GameEvent()
|
||||||
{
|
{
|
||||||
Type = GameEvent.EventType.Script,
|
Type = GameEvent.EventType.ScriptKill,
|
||||||
Data = logLine,
|
Data = logLine,
|
||||||
Origin = server.GetPlayersAsList().First(c => c.NetworkId == lineSplit[1].ConvertLong()),
|
Origin = server.GetPlayersAsList().First(c => c.NetworkId == lineSplit[1].ConvertLong()),
|
||||||
Target = server.GetPlayersAsList().First(c => c.NetworkId == lineSplit[2].ConvertLong()),
|
Target = server.GetPlayersAsList().First(c => c.NetworkId == lineSplit[2].ConvertLong()),
|
||||||
|
@ -20,7 +20,7 @@ namespace IW4MAdmin.Application.EventParsers
|
|||||||
{
|
{
|
||||||
return new GameEvent()
|
return new GameEvent()
|
||||||
{
|
{
|
||||||
Type = GameEvent.EventType.Script,
|
Type = GameEvent.EventType.Kill,
|
||||||
Data = cleanedEventLine,
|
Data = cleanedEventLine,
|
||||||
Origin = server.GetPlayersAsList().First(c => c.ClientNumber == Utilities.ClientIdFromString(lineSplit, 6)),
|
Origin = server.GetPlayersAsList().First(c => c.ClientNumber == Utilities.ClientIdFromString(lineSplit, 6)),
|
||||||
Target = server.GetPlayersAsList().First(c => c.ClientNumber == Utilities.ClientIdFromString(lineSplit, 2)),
|
Target = server.GetPlayersAsList().First(c => c.ClientNumber == Utilities.ClientIdFromString(lineSplit, 2)),
|
||||||
|
@ -3,20 +3,23 @@ using SharedLibraryCore.Interfaces;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace IW4MAdmin.Application
|
namespace IW4MAdmin.Application
|
||||||
{
|
{
|
||||||
class GameEventHandler : IEventHandler
|
class GameEventHandler : IEventHandler
|
||||||
{
|
{
|
||||||
private ConcurrentQueue<GameEvent> EventQueue;
|
private ConcurrentQueue<GameEvent> EventQueue;
|
||||||
private ConcurrentQueue<GameEvent> StatusSensitiveQueue;
|
private Queue<GameEvent> StatusSensitiveQueue;
|
||||||
private IManager Manager;
|
private IManager Manager;
|
||||||
|
|
||||||
public GameEventHandler(IManager mgr)
|
public GameEventHandler(IManager mgr)
|
||||||
{
|
{
|
||||||
EventQueue = new ConcurrentQueue<GameEvent>();
|
EventQueue = new ConcurrentQueue<GameEvent>();
|
||||||
StatusSensitiveQueue = new ConcurrentQueue<GameEvent>();
|
StatusSensitiveQueue = new Queue<GameEvent>();
|
||||||
|
|
||||||
Manager = mgr;
|
Manager = mgr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,25 +29,30 @@ namespace IW4MAdmin.Application
|
|||||||
Manager.GetLogger().WriteDebug($"Got new event of type {gameEvent.Type} for {gameEvent.Owner}");
|
Manager.GetLogger().WriteDebug($"Got new event of type {gameEvent.Type} for {gameEvent.Owner}");
|
||||||
#endif
|
#endif
|
||||||
// we need this to keep accurate track of the score
|
// we need this to keep accurate track of the score
|
||||||
if (gameEvent.Type == GameEvent.EventType.Script ||
|
if (gameEvent.Type == GameEvent.EventType.Kill ||
|
||||||
gameEvent.Type == GameEvent.EventType.Kill ||
|
gameEvent.Type == GameEvent.EventType.Damage ||
|
||||||
|
gameEvent.Type == GameEvent.EventType.ScriptDamage ||
|
||||||
|
gameEvent.Type == GameEvent.EventType.ScriptKill ||
|
||||||
gameEvent.Type == GameEvent.EventType.MapChange)
|
gameEvent.Type == GameEvent.EventType.MapChange)
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
Manager.GetLogger().WriteDebug($"Added sensitive event to queue");
|
Manager.GetLogger().WriteDebug($"Added sensitive event to queue");
|
||||||
#endif
|
#endif
|
||||||
|
lock (StatusSensitiveQueue)
|
||||||
|
{
|
||||||
StatusSensitiveQueue.Enqueue(gameEvent);
|
StatusSensitiveQueue.Enqueue(gameEvent);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
EventQueue.Enqueue(gameEvent);
|
EventQueue.Enqueue(gameEvent);
|
||||||
|
Manager.SetHasEvent();
|
||||||
}
|
}
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
Manager.GetLogger().WriteDebug($"There are now {EventQueue.Count} events in queue");
|
Manager.GetLogger().WriteDebug($"There are now {EventQueue.Count} events in queue");
|
||||||
#endif
|
#endif
|
||||||
Manager.SetHasEvent();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string[] GetEventOutput()
|
public string[] GetEventOutput()
|
||||||
@ -55,6 +63,8 @@ namespace IW4MAdmin.Application
|
|||||||
public GameEvent GetNextSensitiveEvent()
|
public GameEvent GetNextSensitiveEvent()
|
||||||
{
|
{
|
||||||
if (StatusSensitiveQueue.Count > 0)
|
if (StatusSensitiveQueue.Count > 0)
|
||||||
|
{
|
||||||
|
lock (StatusSensitiveQueue)
|
||||||
{
|
{
|
||||||
if (!StatusSensitiveQueue.TryDequeue(out GameEvent newEvent))
|
if (!StatusSensitiveQueue.TryDequeue(out GameEvent newEvent))
|
||||||
{
|
{
|
||||||
@ -66,6 +76,7 @@ namespace IW4MAdmin.Application
|
|||||||
return newEvent;
|
return newEvent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
using SharedLibraryCore;
|
using SharedLibraryCore;
|
||||||
using SharedLibraryCore.Interfaces;
|
using SharedLibraryCore.Interfaces;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace IW4MAdmin.Application.IO
|
namespace IW4MAdmin.Application.IO
|
||||||
@ -14,7 +11,6 @@ namespace IW4MAdmin.Application.IO
|
|||||||
Server Server;
|
Server Server;
|
||||||
long PreviousFileSize;
|
long PreviousFileSize;
|
||||||
GameLogReader Reader;
|
GameLogReader Reader;
|
||||||
Timer RefreshInfoTimer;
|
|
||||||
string GameLogFile;
|
string GameLogFile;
|
||||||
|
|
||||||
class EventState
|
class EventState
|
||||||
@ -28,11 +24,19 @@ namespace IW4MAdmin.Application.IO
|
|||||||
GameLogFile = gameLogPath;
|
GameLogFile = gameLogPath;
|
||||||
Reader = new GameLogReader(gameLogPath, server.EventParser);
|
Reader = new GameLogReader(gameLogPath, server.EventParser);
|
||||||
Server = server;
|
Server = server;
|
||||||
RefreshInfoTimer = new Timer(OnEvent, new EventState()
|
|
||||||
|
Task.Run(async () =>
|
||||||
|
{
|
||||||
|
while (!server.Manager.ShutdownRequested())
|
||||||
|
{
|
||||||
|
OnEvent(new EventState()
|
||||||
{
|
{
|
||||||
Log = server.Manager.GetLogger(),
|
Log = server.Manager.GetLogger(),
|
||||||
ServerId = server.ToString()
|
ServerId = server.ToString()
|
||||||
}, 0, 100);
|
});
|
||||||
|
await Task.Delay(100);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnEvent(object state)
|
private void OnEvent(object state)
|
||||||
|
@ -32,7 +32,7 @@ namespace IW4MAdmin.Application.IO
|
|||||||
string newLine;
|
string newLine;
|
||||||
while (!String.IsNullOrEmpty(newLine = rd.ReadLine()))
|
while (!String.IsNullOrEmpty(newLine = rd.ReadLine()))
|
||||||
{
|
{
|
||||||
logLines.Add(newLine.Replace("\r\n", ""));
|
logLines.Add(newLine);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ namespace IW4MAdmin.Application.IO
|
|||||||
events.Add(Parser.GetEvent(server, eventLine));
|
events.Add(Parser.GetEvent(server, eventLine));
|
||||||
}
|
}
|
||||||
|
|
||||||
catch (Exception e)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ namespace IW4MAdmin.Application
|
|||||||
static public double Version { get; private set; }
|
static public double Version { get; private set; }
|
||||||
static public ApplicationManager ServerManager = ApplicationManager.GetInstance();
|
static public ApplicationManager ServerManager = ApplicationManager.GetInstance();
|
||||||
public static string OperatingDirectory = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + Path.DirectorySeparatorChar;
|
public static string OperatingDirectory = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + Path.DirectorySeparatorChar;
|
||||||
|
private static ManualResetEventSlim OnShutdownComplete = new ManualResetEventSlim();
|
||||||
|
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
@ -43,6 +44,7 @@ namespace IW4MAdmin.Application
|
|||||||
CheckDirectories();
|
CheckDirectories();
|
||||||
|
|
||||||
ServerManager = ApplicationManager.GetInstance();
|
ServerManager = ApplicationManager.GetInstance();
|
||||||
|
Console.CancelKeyPress += new ConsoleCancelEventHandler(OnCancelKey);
|
||||||
Localization.Configure.Initialize(ServerManager.GetApplicationSettings().Configuration()?.CustomLocale);
|
Localization.Configure.Initialize(ServerManager.GetApplicationSettings().Configuration()?.CustomLocale);
|
||||||
loc = Utilities.CurrentLocalization.LocalizationIndex;
|
loc = Utilities.CurrentLocalization.LocalizationIndex;
|
||||||
|
|
||||||
@ -126,30 +128,21 @@ namespace IW4MAdmin.Application
|
|||||||
if (userInput?.Length > 0)
|
if (userInput?.Length > 0)
|
||||||
{
|
{
|
||||||
Origin.CurrentServer = ServerManager.Servers[0];
|
Origin.CurrentServer = ServerManager.Servers[0];
|
||||||
GameEvent E = new GameEvent(GameEvent.EventType.Say, userInput, Origin, null, ServerManager.Servers[0]);
|
GameEvent E = new GameEvent()
|
||||||
|
{
|
||||||
|
Type = GameEvent.EventType.Command,
|
||||||
|
Data = userInput,
|
||||||
|
Origin = Origin,
|
||||||
|
Owner = ServerManager.Servers[0]
|
||||||
|
};
|
||||||
|
|
||||||
ServerManager.GetEventHandler().AddEvent(E);
|
ServerManager.GetEventHandler().AddEvent(E);
|
||||||
|
E.OnProcessed.Wait();
|
||||||
}
|
}
|
||||||
Console.Write('>');
|
Console.Write('>');
|
||||||
|
|
||||||
} while (ServerManager.Running);
|
} while (ServerManager.Running);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (ServerManager.GetApplicationSettings().Configuration().EnableWebFront)
|
|
||||||
{
|
|
||||||
Task.Run(() =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
WebfrontCore.Program.Init(ServerManager);
|
|
||||||
}
|
|
||||||
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
ServerManager.Logger.WriteWarning("Webfront had unhandled exception");
|
|
||||||
ServerManager.Logger.WriteDebug(e.Message);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
@ -164,9 +157,21 @@ namespace IW4MAdmin.Application
|
|||||||
Console.ReadKey();
|
Console.ReadKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ServerManager.GetApplicationSettings().Configuration().EnableWebFront)
|
||||||
|
{
|
||||||
|
Task.Run(() => WebfrontCore.Program.Init(ServerManager));
|
||||||
|
}
|
||||||
|
|
||||||
|
OnShutdownComplete.Reset();
|
||||||
ServerManager.Start().Wait();
|
ServerManager.Start().Wait();
|
||||||
ServerManager.Logger.WriteVerbose(loc["MANAGER_SHUTDOWN_SUCCESS"]);
|
ServerManager.Logger.WriteVerbose(loc["MANAGER_SHUTDOWN_SUCCESS"]);
|
||||||
|
OnShutdownComplete.Set();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void OnCancelKey(object sender, ConsoleCancelEventArgs e)
|
||||||
|
{
|
||||||
|
ServerManager.Stop();
|
||||||
|
OnShutdownComplete.Wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CheckDirectories()
|
static void CheckDirectories()
|
||||||
|
@ -60,17 +60,10 @@ namespace IW4MAdmin.Application
|
|||||||
Api = new EventApi();
|
Api = new EventApi();
|
||||||
ServerEventOccurred += Api.OnServerEvent;
|
ServerEventOccurred += Api.OnServerEvent;
|
||||||
ConfigHandler = new BaseConfigurationHandler<ApplicationConfiguration>("IW4MAdminSettings");
|
ConfigHandler = new BaseConfigurationHandler<ApplicationConfiguration>("IW4MAdminSettings");
|
||||||
Console.CancelKeyPress += new ConsoleCancelEventHandler(OnCancelKey);
|
|
||||||
StartTime = DateTime.UtcNow;
|
StartTime = DateTime.UtcNow;
|
||||||
OnEvent = new ManualResetEventSlim();
|
OnEvent = new ManualResetEventSlim();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnCancelKey(object sender, ConsoleCancelEventArgs args)
|
|
||||||
{
|
|
||||||
Stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public IList<Server> GetServers()
|
public IList<Server> GetServers()
|
||||||
{
|
{
|
||||||
return Servers;
|
return Servers;
|
||||||
@ -141,9 +134,9 @@ namespace IW4MAdmin.Application
|
|||||||
Logger.WriteError($"{Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_EXCEPTION"]} {sensitiveEvent.Owner}");
|
Logger.WriteError($"{Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_EXCEPTION"]} {sensitiveEvent.Owner}");
|
||||||
Logger.WriteDebug("Error Message: " + E.Message);
|
Logger.WriteDebug("Error Message: " + E.Message);
|
||||||
Logger.WriteDebug("Error Trace: " + E.StackTrace);
|
Logger.WriteDebug("Error Trace: " + E.StackTrace);
|
||||||
sensitiveEvent.OnProcessed.Set();
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sensitiveEvent.OnProcessed.Set();
|
||||||
}
|
}
|
||||||
|
|
||||||
await Task.Delay(5000);
|
await Task.Delay(5000);
|
||||||
@ -152,8 +145,8 @@ namespace IW4MAdmin.Application
|
|||||||
|
|
||||||
public async Task Init()
|
public async Task Init()
|
||||||
{
|
{
|
||||||
// setup the event handler after the class is initialized
|
Running = true;
|
||||||
Handler = new GameEventHandler(this);
|
|
||||||
#region DATABASE
|
#region DATABASE
|
||||||
var ipList = (await ClientSvc.Find(c => c.Level > Player.Permission.Trusted))
|
var ipList = (await ClientSvc.Find(c => c.Level > Player.Permission.Trusted))
|
||||||
.Select(c => new
|
.Select(c => new
|
||||||
@ -304,6 +297,8 @@ namespace IW4MAdmin.Application
|
|||||||
#region INIT
|
#region INIT
|
||||||
async Task Init(ServerConfiguration Conf)
|
async Task Init(ServerConfiguration Conf)
|
||||||
{
|
{
|
||||||
|
// setup the event handler after the class is initialized
|
||||||
|
Handler = new GameEventHandler(this);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var ServerInstance = new IW4MServer(this, Conf);
|
var ServerInstance = new IW4MServer(this, Conf);
|
||||||
@ -336,8 +331,6 @@ namespace IW4MAdmin.Application
|
|||||||
|
|
||||||
await Task.WhenAll(config.Servers.Select(c => Init(c)).ToArray());
|
await Task.WhenAll(config.Servers.Select(c => Init(c)).ToArray());
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
Running = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SendHeartbeat(object state)
|
private void SendHeartbeat(object state)
|
||||||
@ -419,6 +412,12 @@ namespace IW4MAdmin.Application
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this happens if a plugin requires login
|
||||||
|
catch (AuthorizationException e)
|
||||||
|
{
|
||||||
|
await newEvent.Origin.Tell($"{Utilities.CurrentLocalization.LocalizationIndex["COMMAND_NOTAUTHORIZED"]} - {e.Message}");
|
||||||
|
}
|
||||||
|
|
||||||
catch (NetworkException e)
|
catch (NetworkException e)
|
||||||
{
|
{
|
||||||
Logger.WriteError(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_COMMUNICATION"]);
|
Logger.WriteError(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_COMMUNICATION"]);
|
||||||
@ -449,9 +448,7 @@ namespace IW4MAdmin.Application
|
|||||||
}
|
}
|
||||||
|
|
||||||
// this should allow parallel processing of events
|
// this should allow parallel processing of events
|
||||||
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
await Task.WhenAll(eventList);
|
||||||
Task.WhenAll(eventList);
|
|
||||||
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
|
||||||
|
|
||||||
// signal that all events have been processed
|
// signal that all events have been processed
|
||||||
OnEvent.Reset();
|
OnEvent.Reset();
|
||||||
@ -459,8 +456,8 @@ namespace IW4MAdmin.Application
|
|||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
HeartbeatTimer.Change(0, Timeout.Infinite);
|
HeartbeatTimer.Change(0, Timeout.Infinite);
|
||||||
|
|
||||||
foreach (var S in Servers)
|
foreach (var S in _servers)
|
||||||
S.Broadcast("^1" + Utilities.CurrentLocalization.LocalizationIndex["BROADCAST_OFFLINE"]).Wait();
|
await S.Broadcast("^1" + Utilities.CurrentLocalization.LocalizationIndex["BROADCAST_OFFLINE"]);
|
||||||
#endif
|
#endif
|
||||||
_servers.Clear();
|
_servers.Clear();
|
||||||
}
|
}
|
||||||
|
@ -23,11 +23,12 @@ namespace Application.RconParsers
|
|||||||
TempBan = "tempbanclient {0} \"{1}\""
|
TempBan = "tempbanclient {0} \"{1}\""
|
||||||
};
|
};
|
||||||
|
|
||||||
private static string StatusRegex = @"^( *[0-9]+) +-*([0-9]+) +((?:[A-Z]+|[0-9]+)) +((?:[a-z]|[0-9]){16}|bot[0-9]+) +(.{0,20}) +([0-9]+) +(\d+\.\d+\.\d+.\d+\:-*\d{1,5}|0+.0+:-*\d{1,5}) +(-*[0-9]+) +([0-9]+) *$";
|
private static string StatusRegex = @"^( *[0-9]+) +-*([0-9]+) +((?:[A-Z]+|[0-9]+)) +((?:[a-z]|[0-9]){16}|bot[0-9]+|(?:[0-9]+)) +(.{0,20}) +([0-9]+) +(\d+\.\d+\.\d+.\d+\:-*\d{1,5}|0+.0+:-*\d{1,5}) +(-*[0-9]+) +([0-9]+) *$";
|
||||||
|
|
||||||
public async Task<string[]> ExecuteCommandAsync(Connection connection, string command)
|
public async Task<string[]> ExecuteCommandAsync(Connection connection, string command)
|
||||||
{
|
{
|
||||||
return (await connection.SendQueryAsync(StaticHelpers.QueryType.COMMAND, command)).Skip(1).ToArray();
|
var response = await connection.SendQueryAsync(StaticHelpers.QueryType.COMMAND, command);
|
||||||
|
return response.Skip(1).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Dvar<T>> GetDvarAsync<T>(Connection connection, string dvarName)
|
public async Task<Dvar<T>> GetDvarAsync<T>(Connection connection, string dvarName)
|
||||||
|
@ -25,11 +25,9 @@ namespace IW4MAdmin
|
|||||||
{
|
{
|
||||||
public class IW4MServer : Server
|
public class IW4MServer : Server
|
||||||
{
|
{
|
||||||
private CancellationToken cts;
|
|
||||||
private static Index loc = Utilities.CurrentLocalization.LocalizationIndex;
|
private static Index loc = Utilities.CurrentLocalization.LocalizationIndex;
|
||||||
private GameLogEvent LogEvent;
|
private GameLogEvent LogEvent;
|
||||||
|
|
||||||
|
|
||||||
public IW4MServer(IManager mgr, ServerConfiguration cfg) : base(mgr, cfg) { }
|
public IW4MServer(IManager mgr, ServerConfiguration cfg) : base(mgr, cfg) { }
|
||||||
|
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
@ -196,17 +194,22 @@ namespace IW4MAdmin
|
|||||||
|
|
||||||
Logger.WriteInfo($"Client {player} connecting...");
|
Logger.WriteInfo($"Client {player} connecting...");
|
||||||
|
|
||||||
var e = new GameEvent(GameEvent.EventType.Connect, "", player, null, this);
|
|
||||||
Manager.GetEventHandler().AddEvent(e);
|
|
||||||
|
|
||||||
e.OnProcessed.WaitHandle.WaitOne(5000);
|
|
||||||
|
|
||||||
if (!Manager.GetApplicationSettings().Configuration().EnableClientVPNs &&
|
if (!Manager.GetApplicationSettings().Configuration().EnableClientVPNs &&
|
||||||
await VPNCheck.UsingVPN(player.IPAddressString, Manager.GetApplicationSettings().Configuration().IPHubAPIKey))
|
await VPNCheck.UsingVPN(player.IPAddressString, Manager.GetApplicationSettings().Configuration().IPHubAPIKey))
|
||||||
{
|
{
|
||||||
await player.Kick(Utilities.CurrentLocalization.LocalizationIndex["SERVER_KICK_VPNS_NOTALLOWED"], new Player() { ClientId = 1 });
|
await player.Kick(Utilities.CurrentLocalization.LocalizationIndex["SERVER_KICK_VPNS_NOTALLOWED"], new Player() { ClientId = 1 });
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var e = new GameEvent()
|
||||||
|
{
|
||||||
|
Type = GameEvent.EventType.Connect,
|
||||||
|
Origin = player,
|
||||||
|
Owner = this
|
||||||
|
};
|
||||||
|
Manager.GetEventHandler().AddEvent(e);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -375,14 +378,31 @@ namespace IW4MAdmin
|
|||||||
await ProcessEvent(E);
|
await ProcessEvent(E);
|
||||||
Manager.GetEventApi().OnServerEvent(this, E);
|
Manager.GetEventApi().OnServerEvent(this, E);
|
||||||
|
|
||||||
|
|
||||||
|
Command C = null;
|
||||||
|
if (E.Type == GameEvent.EventType.Command)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
C = await ValidateCommand(E);
|
||||||
|
}
|
||||||
|
|
||||||
|
catch (CommandException e)
|
||||||
|
{
|
||||||
|
Logger.WriteInfo(e.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (C != null)
|
||||||
|
{
|
||||||
|
E.Extra = C;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// this allows us to catch exceptions but still run it parallel
|
// this allows us to catch exceptions but still run it parallel
|
||||||
async Task pluginHandlingAsync(Task onEvent, string pluginName)
|
async Task pluginHandlingAsync(Task onEvent, string pluginName)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (cts.IsCancellationRequested)
|
|
||||||
return;
|
|
||||||
|
|
||||||
await onEvent;
|
await onEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -467,44 +487,7 @@ namespace IW4MAdmin
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (E.Type == GameEvent.EventType.Script)
|
|
||||||
{
|
|
||||||
Manager.GetEventHandler().AddEvent(GameEvent.TransferWaiter(GameEvent.EventType.Kill, E));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (E.Type == GameEvent.EventType.Say && E.Data?.Length >= 2)
|
if (E.Type == GameEvent.EventType.Say && E.Data?.Length >= 2)
|
||||||
{
|
|
||||||
if (E.Data.Substring(0, 1) == "!" ||
|
|
||||||
E.Data.Substring(0, 1) == "@" ||
|
|
||||||
E.Origin.Level == Player.Permission.Console)
|
|
||||||
{
|
|
||||||
Command C = null;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
C = await ValidateCommand(E);
|
|
||||||
}
|
|
||||||
|
|
||||||
catch (CommandException e)
|
|
||||||
{
|
|
||||||
Logger.WriteInfo(e.Message);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (C != null)
|
|
||||||
{
|
|
||||||
if (C.RequiresTarget && E.Target == null)
|
|
||||||
{
|
|
||||||
Logger.WriteWarning("Requested event (command) requiring target does not have a target!");
|
|
||||||
}
|
|
||||||
|
|
||||||
E.Extra = C;
|
|
||||||
|
|
||||||
// reprocess event as a command
|
|
||||||
Manager.GetEventHandler().AddEvent(GameEvent.TransferWaiter(GameEvent.EventType.Command, E));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else // Not a command
|
|
||||||
{
|
{
|
||||||
E.Data = E.Data.StripColors();
|
E.Data = E.Data.StripColors();
|
||||||
|
|
||||||
@ -515,7 +498,6 @@ namespace IW4MAdmin
|
|||||||
Time = DateTime.UtcNow
|
Time = DateTime.UtcNow
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (E.Type == GameEvent.EventType.MapChange)
|
if (E.Type == GameEvent.EventType.MapChange)
|
||||||
{
|
{
|
||||||
@ -533,7 +515,6 @@ namespace IW4MAdmin
|
|||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
Gametype = dict["gametype"].StripColors();
|
Gametype = dict["gametype"].StripColors();
|
||||||
Hostname = dict["hostname"]?.StripColors();
|
Hostname = dict["hostname"]?.StripColors();
|
||||||
|
|
||||||
@ -549,7 +530,11 @@ namespace IW4MAdmin
|
|||||||
Hostname = dict["sv_hostname"].StripColors();
|
Hostname = dict["sv_hostname"].StripColors();
|
||||||
|
|
||||||
string mapname = dict["mapname"].StripColors();
|
string mapname = dict["mapname"].StripColors();
|
||||||
CurrentMap = Maps.Find(m => m.Name == mapname) ?? new Map() { Alias = mapname, Name = mapname };
|
CurrentMap = Maps.Find(m => m.Name == mapname) ?? new Map()
|
||||||
|
{
|
||||||
|
Alias = mapname,
|
||||||
|
Name = mapname
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -569,7 +554,6 @@ namespace IW4MAdmin
|
|||||||
await E.Owner.ExecuteCommandAsync(E.Message);
|
await E.Owner.ExecuteCommandAsync(E.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
//todo: move
|
|
||||||
while (ChatHistory.Count > Math.Ceiling((double)ClientNum / 2))
|
while (ChatHistory.Count > Math.Ceiling((double)ClientNum / 2))
|
||||||
ChatHistory.RemoveAt(0);
|
ChatHistory.RemoveAt(0);
|
||||||
|
|
||||||
@ -634,18 +618,15 @@ namespace IW4MAdmin
|
|||||||
|
|
||||||
override public async Task<bool> ProcessUpdatesAsync(CancellationToken cts)
|
override public async Task<bool> ProcessUpdatesAsync(CancellationToken cts)
|
||||||
{
|
{
|
||||||
// this isn't really used anymore
|
|
||||||
this.cts = cts;
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (Manager.ShutdownRequested())
|
if (Manager.ShutdownRequested())
|
||||||
{
|
{
|
||||||
foreach (var plugin in SharedLibraryCore.Plugins.PluginImporter.ActivePlugins)
|
|
||||||
await plugin.OnUnloadAsync();
|
|
||||||
|
|
||||||
for (int i = 0; i < Players.Count; i++)
|
for (int i = 0; i < Players.Count; i++)
|
||||||
await RemovePlayer(i);
|
await RemovePlayer(i);
|
||||||
|
|
||||||
|
foreach (var plugin in SharedLibraryCore.Plugins.PluginImporter.ActivePlugins)
|
||||||
|
await plugin.OnUnloadAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
// only check every 2 minutes if the server doesn't seem to be responding
|
// only check every 2 minutes if the server doesn't seem to be responding
|
||||||
@ -746,7 +727,6 @@ namespace IW4MAdmin
|
|||||||
if (ServerConfig.UseIW5MParser)
|
if (ServerConfig.UseIW5MParser)
|
||||||
RconParser = new IW5MRConParser();
|
RconParser = new IW5MRConParser();
|
||||||
|
|
||||||
|
|
||||||
var version = await this.GetDvarAsync<string>("version");
|
var version = await this.GetDvarAsync<string>("version");
|
||||||
GameName = Utilities.GetGame(version.Value);
|
GameName = Utilities.GetGame(version.Value);
|
||||||
|
|
||||||
@ -838,7 +818,6 @@ namespace IW4MAdmin
|
|||||||
$"{basepath.Value.Replace('\\', Path.DirectorySeparatorChar)}{Path.DirectorySeparatorChar}{game.Replace('/', Path.DirectorySeparatorChar)}{Path.DirectorySeparatorChar}{logfile.Value}";
|
$"{basepath.Value.Replace('\\', Path.DirectorySeparatorChar)}{Path.DirectorySeparatorChar}{game.Replace('/', Path.DirectorySeparatorChar)}{Path.DirectorySeparatorChar}{logfile.Value}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// hopefully fix wine drive name mangling
|
// hopefully fix wine drive name mangling
|
||||||
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
{
|
{
|
||||||
|
@ -13,12 +13,13 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
|
|||||||
class Detection
|
class Detection
|
||||||
{
|
{
|
||||||
int Kills;
|
int Kills;
|
||||||
|
int HitCount;
|
||||||
int AboveThresholdCount;
|
int AboveThresholdCount;
|
||||||
double AverageKillTime;
|
double AverageKillTime;
|
||||||
Dictionary<IW4Info.HitLocation, int> HitLocationCount;
|
Dictionary<IW4Info.HitLocation, int> HitLocationCount;
|
||||||
double AngleDifferenceAverage;
|
double AngleDifferenceAverage;
|
||||||
EFClientStatistics ClientStats;
|
EFClientStatistics ClientStats;
|
||||||
DateTime LastKill;
|
DateTime LastHit;
|
||||||
long LastOffset;
|
long LastOffset;
|
||||||
ILogger Log;
|
ILogger Log;
|
||||||
Strain Strain;
|
Strain Strain;
|
||||||
@ -74,22 +75,21 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
|
|||||||
ClientPenalty = Penalty.PenaltyType.Any,
|
ClientPenalty = Penalty.PenaltyType.Any,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (LastKill == DateTime.MinValue)
|
if (LastHit == DateTime.MinValue)
|
||||||
LastKill = DateTime.UtcNow;
|
LastHit = DateTime.UtcNow;
|
||||||
|
|
||||||
HitLocationCount[kill.HitLoc]++;
|
HitLocationCount[kill.HitLoc]++;
|
||||||
if (!isDamage)
|
if (!isDamage)
|
||||||
{
|
{
|
||||||
Kills++;
|
Kills++;
|
||||||
AverageKillTime = (AverageKillTime + (DateTime.UtcNow - LastKill).TotalSeconds) / Kills;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HitCount++;
|
||||||
|
|
||||||
#region VIEWANGLES
|
#region VIEWANGLES
|
||||||
if (kill.AnglesList.Count >= 2)
|
if (kill.AnglesList.Count >= 2)
|
||||||
{
|
{
|
||||||
double realAgainstPredict = Math.Abs(Vector3.AbsoluteDistance(kill.AnglesList[0], kill.AnglesList[1]) -
|
double realAgainstPredict = Vector3.ViewAngleDistance(kill.AnglesList[0], kill.AnglesList[1], kill.ViewAngles);
|
||||||
(Vector3.AbsoluteDistance(kill.AnglesList[0], kill.ViewAngles) +
|
|
||||||
Vector3.AbsoluteDistance(kill.AnglesList[1], kill.ViewAngles)));
|
|
||||||
|
|
||||||
// LIFETIME
|
// LIFETIME
|
||||||
var hitLoc = ClientStats.HitLocations
|
var hitLoc = ClientStats.HitLocations
|
||||||
@ -102,26 +102,37 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
|
|||||||
|
|
||||||
if (hitLoc.HitOffsetAverage > Thresholds.MaxOffset)
|
if (hitLoc.HitOffsetAverage > Thresholds.MaxOffset)
|
||||||
{
|
{
|
||||||
|
Log.WriteDebug("*** Reached Max Lifetime Average for Angle Difference ***");
|
||||||
|
Log.WriteDebug($"Lifetime Average = {newAverage}");
|
||||||
|
Log.WriteDebug($"Bone = {hitLoc.Location}");
|
||||||
|
Log.WriteDebug($"HitCount = {hitLoc.HitCount}");
|
||||||
|
Log.WriteDebug($"ID = {kill.AttackerId}");
|
||||||
|
|
||||||
return new DetectionPenaltyResult()
|
return new DetectionPenaltyResult()
|
||||||
{
|
{
|
||||||
ClientPenalty = Penalty.PenaltyType.Ban,
|
ClientPenalty = Penalty.PenaltyType.Flag,
|
||||||
RatioAmount = hitLoc.HitOffsetAverage,
|
RatioAmount = hitLoc.HitOffsetAverage,
|
||||||
KillCount = ClientStats.SessionKills,
|
KillCount = hitLoc.HitCount,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// SESSION
|
// SESSION
|
||||||
int sessHitLocCount = HitLocationCount[kill.HitLoc];
|
double sessAverage = (AngleDifferenceAverage * (HitCount - 1) + realAgainstPredict) / HitCount;
|
||||||
double sessAverage = (AngleDifferenceAverage * (sessHitLocCount - 1)) + realAgainstPredict / sessHitLocCount;
|
|
||||||
AngleDifferenceAverage = sessAverage;
|
AngleDifferenceAverage = sessAverage;
|
||||||
|
|
||||||
if (sessAverage > Thresholds.MaxOffset)
|
if (sessAverage > Thresholds.MaxOffset)
|
||||||
{
|
{
|
||||||
|
Log.WriteDebug("*** Reached Max Session Average for Angle Difference ***");
|
||||||
|
Log.WriteDebug($"Session Average = {sessAverage}");
|
||||||
|
// Log.WriteDebug($"Bone = {hitLoc.Location}");
|
||||||
|
Log.WriteDebug($"HitCount = {HitCount}");
|
||||||
|
Log.WriteDebug($"ID = {kill.AttackerId}");
|
||||||
|
|
||||||
return new DetectionPenaltyResult()
|
return new DetectionPenaltyResult()
|
||||||
{
|
{
|
||||||
ClientPenalty = Penalty.PenaltyType.Ban,
|
ClientPenalty = Penalty.PenaltyType.Flag,
|
||||||
RatioAmount = sessHitLocCount,
|
RatioAmount = sessAverage,
|
||||||
KillCount = ClientStats.SessionKills,
|
KillCount = HitCount,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,7 +141,9 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
var currentStrain = Strain.GetStrain(kill.ViewAngles, kill.TimeOffset - LastOffset);
|
double diff = Math.Max(50, kill.TimeOffset - LastOffset);
|
||||||
|
var currentStrain = Strain.GetStrain(kill.ViewAngles, diff);
|
||||||
|
//LastHit = kill.When;
|
||||||
LastOffset = kill.TimeOffset;
|
LastOffset = kill.TimeOffset;
|
||||||
|
|
||||||
if (currentStrain > ClientStats.MaxStrain)
|
if (currentStrain > ClientStats.MaxStrain)
|
||||||
@ -138,29 +151,38 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
|
|||||||
ClientStats.MaxStrain = currentStrain;
|
ClientStats.MaxStrain = currentStrain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (currentStrain > Thresholds.MaxStrain)
|
||||||
|
{
|
||||||
|
Log.WriteDebug("*** Reached Max Strain ***");
|
||||||
|
Log.WriteDebug($"Strain = {currentStrain}");
|
||||||
|
Log.WriteDebug($"Angles = {kill.ViewAngles} {kill.AnglesList[0]} {kill.AnglesList[1]}");
|
||||||
|
Log.WriteDebug($"Time = {diff}");
|
||||||
|
Log.WriteDebug($"HitCount = {HitCount}");
|
||||||
|
Log.WriteDebug($"ID = {kill.AttackerId}");
|
||||||
|
}
|
||||||
|
|
||||||
if (Strain.TimesReachedMaxStrain >= 3)
|
if (Strain.TimesReachedMaxStrain >= 3)
|
||||||
{
|
{
|
||||||
return new DetectionPenaltyResult()
|
return new DetectionPenaltyResult()
|
||||||
{
|
{
|
||||||
ClientPenalty = Penalty.PenaltyType.Ban,
|
ClientPenalty = Penalty.PenaltyType.Flag,
|
||||||
RatioAmount = ClientStats.MaxStrain,
|
RatioAmount = ClientStats.MaxStrain,
|
||||||
KillCount = ClientStats.SessionKills,
|
KillCount = HitCount,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
Log.WriteDebug($"Current Strain: {currentStrain}");
|
Log.WriteDebug($"Current Strain: {currentStrain}");
|
||||||
#endif
|
#endif
|
||||||
LastKill = kill.When;
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region SESSION_RATIOS
|
#region SESSION_RATIOS
|
||||||
if (Kills >= Thresholds.LowSampleMinKills)
|
if (Kills >= Thresholds.LowSampleMinKills)
|
||||||
{
|
{
|
||||||
double marginOfError = Thresholds.GetMarginOfError(Kills);
|
double marginOfError = Thresholds.GetMarginOfError(HitCount);
|
||||||
// determine what the max headshot percentage can be for current number of kills
|
// determine what the max headshot percentage can be for current number of kills
|
||||||
double lerpAmount = Math.Min(1.0, (Kills - Thresholds.LowSampleMinKills) / (double)(/*Thresholds.HighSampleMinKills*/ 60 - Thresholds.LowSampleMinKills));
|
double lerpAmount = Math.Min(1.0, (HitCount - Thresholds.LowSampleMinKills) / (double)(/*Thresholds.HighSampleMinKills*/ 60 - Thresholds.LowSampleMinKills));
|
||||||
double maxHeadshotLerpValueForFlag = Thresholds.Lerp(Thresholds.HeadshotRatioThresholdLowSample(2.0), Thresholds.HeadshotRatioThresholdHighSample(2.0), lerpAmount) + marginOfError;
|
double maxHeadshotLerpValueForFlag = Thresholds.Lerp(Thresholds.HeadshotRatioThresholdLowSample(2.0), Thresholds.HeadshotRatioThresholdHighSample(2.0), lerpAmount) + marginOfError;
|
||||||
double maxHeadshotLerpValueForBan = Thresholds.Lerp(Thresholds.HeadshotRatioThresholdLowSample(3.0), Thresholds.HeadshotRatioThresholdHighSample(3.0), lerpAmount) + marginOfError;
|
double maxHeadshotLerpValueForBan = Thresholds.Lerp(Thresholds.HeadshotRatioThresholdLowSample(3.0), Thresholds.HeadshotRatioThresholdHighSample(3.0), lerpAmount) + marginOfError;
|
||||||
// determine what the max bone percentage can be for current number of kills
|
// determine what the max bone percentage can be for current number of kills
|
||||||
@ -168,10 +190,10 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
|
|||||||
double maxBoneRatioLerpValueForBan = Thresholds.Lerp(Thresholds.BoneRatioThresholdLowSample(3.25), Thresholds.BoneRatioThresholdHighSample(3.25), lerpAmount) + marginOfError;
|
double maxBoneRatioLerpValueForBan = Thresholds.Lerp(Thresholds.BoneRatioThresholdLowSample(3.25), Thresholds.BoneRatioThresholdHighSample(3.25), lerpAmount) + marginOfError;
|
||||||
|
|
||||||
// calculate headshot ratio
|
// calculate headshot ratio
|
||||||
double currentHeadshotRatio = ((HitLocationCount[IW4Info.HitLocation.head] + HitLocationCount[IW4Info.HitLocation.helmet] + HitLocationCount[IW4Info.HitLocation.neck]) / (double)Kills);
|
double currentHeadshotRatio = ((HitLocationCount[IW4Info.HitLocation.head] + HitLocationCount[IW4Info.HitLocation.helmet] + HitLocationCount[IW4Info.HitLocation.neck]) / (double)HitCount);
|
||||||
|
|
||||||
// calculate maximum bone
|
// calculate maximum bone
|
||||||
double currentMaxBoneRatio = (HitLocationCount.Values.Select(v => v / (double)Kills).Max());
|
double currentMaxBoneRatio = (HitLocationCount.Values.Select(v => v / (double)HitCount).Max());
|
||||||
var bone = HitLocationCount.FirstOrDefault(b => b.Value == HitLocationCount.Values.Max()).Key;
|
var bone = HitLocationCount.FirstOrDefault(b => b.Value == HitLocationCount.Values.Max()).Key;
|
||||||
|
|
||||||
#region HEADSHOT_RATIO
|
#region HEADSHOT_RATIO
|
||||||
|
@ -132,7 +132,6 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
|||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// todo: look at this more
|
|
||||||
statsSvc.ClientStatSvc.Update(clientStats);
|
statsSvc.ClientStatSvc.Update(clientStats);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,10 +200,9 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
|||||||
playerStats.TryRemove(pl.ClientId, out EFClientStatistics removedValue3);
|
playerStats.TryRemove(pl.ClientId, out EFClientStatistics removedValue3);
|
||||||
detectionStats.TryRemove(pl.ClientId, out Cheat.Detection removedValue4);
|
detectionStats.TryRemove(pl.ClientId, out Cheat.Detection removedValue4);
|
||||||
|
|
||||||
/* // sync their stats before they leave
|
// sync their stats before they leave
|
||||||
clientStats = UpdateStats(clientStats);*/
|
//clientStats = UpdateStats(clientStats);
|
||||||
|
|
||||||
// todo: should this be saved every disconnect?
|
|
||||||
statsSvc.ClientStatSvc.Update(clientStats);
|
statsSvc.ClientStatSvc.Update(clientStats);
|
||||||
await statsSvc.ClientStatSvc.SaveChangesAsync();
|
await statsSvc.ClientStatSvc.SaveChangesAsync();
|
||||||
// increment the total play time
|
// increment the total play time
|
||||||
@ -225,7 +223,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
|||||||
/// Process stats for kill event
|
/// Process stats for kill event
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task AddScriptKill(bool isDamage, DateTime time, Player attacker, Player victim, int serverId, string map, string hitLoc, string type,
|
public async Task AddScriptHit(bool isDamage, DateTime time, Player attacker, Player victim, int serverId, string map, string hitLoc, string type,
|
||||||
string damage, string weapon, string killOrigin, string deathOrigin, string viewAngles, string offset, string isKillstreakKill, string Ads, string snapAngles)
|
string damage, string weapon, string killOrigin, string deathOrigin, string viewAngles, string offset, string isKillstreakKill, string Ads, string snapAngles)
|
||||||
{
|
{
|
||||||
var statsSvc = ContextThreads[serverId];
|
var statsSvc = ContextThreads[serverId];
|
||||||
@ -312,7 +310,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
|||||||
{
|
{
|
||||||
clientStats.HitLocations.Single(hl => hl.Location == kill.HitLoc).HitCount += 1;
|
clientStats.HitLocations.Single(hl => hl.Location == kill.HitLoc).HitCount += 1;
|
||||||
|
|
||||||
statsSvc.ClientStatSvc.Update(clientStats);
|
//statsSvc.ClientStatSvc.Update(clientStats);
|
||||||
// await statsSvc.ClientStatSvc.SaveChangesAsync();
|
// await statsSvc.ClientStatSvc.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -500,7 +498,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
|||||||
{
|
{
|
||||||
scoreDifference = clientStats.RoundScore + clientStats.LastScore;
|
scoreDifference = clientStats.RoundScore + clientStats.LastScore;
|
||||||
}
|
}
|
||||||
else
|
else if (clientStats.RoundScore > 0 && clientStats.LastScore < clientStats.RoundScore)
|
||||||
{
|
{
|
||||||
scoreDifference = clientStats.RoundScore - clientStats.LastScore;
|
scoreDifference = clientStats.RoundScore - clientStats.LastScore;
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,8 @@ namespace IW4MAdmin.Plugins.Stats
|
|||||||
await Manager.RemovePlayer(E.Origin);
|
await Manager.RemovePlayer(E.Origin);
|
||||||
break;
|
break;
|
||||||
case GameEvent.EventType.Say:
|
case GameEvent.EventType.Say:
|
||||||
if (E.Data != string.Empty && E.Data.Trim().Length > 0 && E.Message.Trim()[0] != '!' && E.Origin.ClientId > 1)
|
if (!string.IsNullOrEmpty(E.Data) &&
|
||||||
|
E.Origin.ClientId > 1)
|
||||||
await Manager.AddMessageAsync(E.Origin.ClientId, E.Owner.GetHashCode(), E.Data);
|
await Manager.AddMessageAsync(E.Origin.ClientId, E.Owner.GetHashCode(), E.Data);
|
||||||
break;
|
break;
|
||||||
case GameEvent.EventType.MapChange:
|
case GameEvent.EventType.MapChange:
|
||||||
@ -69,23 +70,26 @@ namespace IW4MAdmin.Plugins.Stats
|
|||||||
break;
|
break;
|
||||||
case GameEvent.EventType.Flag:
|
case GameEvent.EventType.Flag:
|
||||||
break;
|
break;
|
||||||
case GameEvent.EventType.Script:
|
case GameEvent.EventType.ScriptKill:
|
||||||
|
string[] killInfo = (E.Data != null) ? E.Data.Split(';') : new string[0];
|
||||||
|
if (killInfo.Length >= 13)
|
||||||
|
await Manager.AddScriptHit(false, E.Time, E.Origin, E.Target, S.GetHashCode(), S.CurrentMap.Name, killInfo[7], killInfo[8],
|
||||||
|
killInfo[5], killInfo[6], killInfo[3], killInfo[4], killInfo[9], killInfo[10], killInfo[11], killInfo[12], killInfo[13]);
|
||||||
break;
|
break;
|
||||||
case GameEvent.EventType.Kill:
|
case GameEvent.EventType.Kill:
|
||||||
string[] killInfo = (E.Data != null) ? E.Data.Split(';') : new string[0];
|
if (!E.Owner.CustomCallback)
|
||||||
if (killInfo.Length >= 9 && killInfo[0].Contains("ScriptKill") && E.Owner.CustomCallback)
|
|
||||||
await Manager.AddScriptKill(false, E.Time, E.Origin, E.Target, S.GetHashCode(), S.CurrentMap.Name, killInfo[7], killInfo[8],
|
|
||||||
killInfo[5], killInfo[6], killInfo[3], killInfo[4], killInfo[9], killInfo[10], killInfo[11], killInfo[12], killInfo[13]);
|
|
||||||
else if (!E.Owner.CustomCallback)
|
|
||||||
await Manager.AddStandardKill(E.Origin, E.Target);
|
await Manager.AddStandardKill(E.Origin, E.Target);
|
||||||
break;
|
break;
|
||||||
case GameEvent.EventType.Death:
|
case GameEvent.EventType.Death:
|
||||||
break;
|
break;
|
||||||
//case GameEvent.EventType.Damage:
|
case GameEvent.EventType.Damage:
|
||||||
|
if (!E.Owner.CustomCallback)
|
||||||
|
Manager.AddDamageEvent(E.Data, E.Origin.ClientId, E.Owner.GetHashCode());
|
||||||
|
break;
|
||||||
case GameEvent.EventType.ScriptDamage:
|
case GameEvent.EventType.ScriptDamage:
|
||||||
killInfo = (E.Data != null) ? E.Data.Split(';') : new string[0];
|
killInfo = (E.Data != null) ? E.Data.Split(';') : new string[0];
|
||||||
if (killInfo.Length >= 9 && E.Owner.CustomCallback)
|
if (killInfo.Length >= 13)
|
||||||
await Manager.AddScriptKill(true, E.Time, E.Origin, E.Target, S.GetHashCode(), S.CurrentMap.Name, killInfo[7], killInfo[8],
|
await Manager.AddScriptHit(true, E.Time, E.Origin, E.Target, S.GetHashCode(), S.CurrentMap.Name, killInfo[7], killInfo[8],
|
||||||
killInfo[5], killInfo[6], killInfo[3], killInfo[4], killInfo[9], killInfo[10], killInfo[11], killInfo[12], killInfo[13]);
|
killInfo[5], killInfo[6], killInfo[3], killInfo[4], killInfo[9], killInfo[10], killInfo[11], killInfo[12], killInfo[13]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -689,7 +689,6 @@ namespace SharedLibraryCore.Commands
|
|||||||
|
|
||||||
public override async Task ExecuteAsync(GameEvent E)
|
public override async Task ExecuteAsync(GameEvent E)
|
||||||
{
|
{
|
||||||
// todo: move unflag to seperate command
|
|
||||||
if (E.Target.Level >= E.Origin.Level)
|
if (E.Target.Level >= E.Origin.Level)
|
||||||
{
|
{
|
||||||
await E.Origin.Tell($"{Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_FLAG_FAIL"]} ^5{E.Target.Name}");
|
await E.Origin.Tell($"{Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_FLAG_FAIL"]} ^5{E.Target.Name}");
|
||||||
|
@ -33,8 +33,8 @@ namespace SharedLibraryCore
|
|||||||
Command,
|
Command,
|
||||||
|
|
||||||
// FROM GAME
|
// FROM GAME
|
||||||
Script,
|
|
||||||
ScriptDamage,
|
ScriptDamage,
|
||||||
|
ScriptKill,
|
||||||
Kill,
|
Kill,
|
||||||
Damage,
|
Damage,
|
||||||
Death,
|
Death,
|
||||||
@ -49,35 +49,19 @@ namespace SharedLibraryCore
|
|||||||
Owner = S;
|
Owner = S;
|
||||||
OnProcessed = new ManualResetEventSlim();
|
OnProcessed = new ManualResetEventSlim();
|
||||||
Time = DateTime.UtcNow;
|
Time = DateTime.UtcNow;
|
||||||
|
CurrentEventId++;
|
||||||
|
Id = CurrentEventId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public GameEvent()
|
public GameEvent()
|
||||||
{
|
{
|
||||||
OnProcessed = new ManualResetEventSlim();
|
OnProcessed = new ManualResetEventSlim();
|
||||||
Time = DateTime.UtcNow;
|
Time = DateTime.UtcNow;
|
||||||
|
CurrentEventId++;
|
||||||
|
Id = CurrentEventId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static GameEvent TransferWaiter(EventType newType, GameEvent e)
|
private static long CurrentEventId;
|
||||||
{
|
|
||||||
var newEvent = new GameEvent()
|
|
||||||
{
|
|
||||||
Data = e.Data,
|
|
||||||
Extra = e.Extra,
|
|
||||||
Message = e.Message,
|
|
||||||
OnProcessed = e.OnProcessed,
|
|
||||||
Origin = e.Origin,
|
|
||||||
Owner = e.Owner,
|
|
||||||
Remote = e.Remote,
|
|
||||||
Target = e.Target,
|
|
||||||
Type = newType,
|
|
||||||
};
|
|
||||||
|
|
||||||
// hack: prevent the previous event from completing until this one is done
|
|
||||||
e.OnProcessed = new ManualResetEventSlim();
|
|
||||||
newEvent.Time = e.Time;
|
|
||||||
|
|
||||||
return newEvent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public EventType Type;
|
public EventType Type;
|
||||||
public string Data; // Data is usually the message sent by player
|
public string Data; // Data is usually the message sent by player
|
||||||
@ -89,5 +73,6 @@ namespace SharedLibraryCore
|
|||||||
public object Extra { get; set; }
|
public object Extra { get; set; }
|
||||||
public ManualResetEventSlim OnProcessed { get; set; }
|
public ManualResetEventSlim OnProcessed { get; set; }
|
||||||
public DateTime Time { get; private set; }
|
public DateTime Time { get; private set; }
|
||||||
|
public long Id { get; private set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,16 +48,41 @@ namespace SharedLibraryCore.Helpers
|
|||||||
{
|
{
|
||||||
double deltaX = Math.Abs(b.X -a.X);
|
double deltaX = Math.Abs(b.X -a.X);
|
||||||
double deltaY = Math.Abs(b.Y - a.Y);
|
double deltaY = Math.Abs(b.Y - a.Y);
|
||||||
// double deltaZ = Math.Abs(b.Z - a.Z);
|
double deltaZ = Math.Abs(b.Z - a.Z);
|
||||||
|
|
||||||
// this 'fixes' the roll-over angles
|
// this 'fixes' the roll-over angles
|
||||||
double dx = deltaX < 360.0 / 2 ? deltaX : 360.0 - deltaX;
|
double dx = deltaX < 360.0 / 2 ? deltaX : 360.0 - deltaX;
|
||||||
double dy = deltaY < 360.0 / 2 ? deltaY : 360.0 - deltaY;
|
double dy = deltaY < 360.0 / 2 ? deltaY : 360.0 - deltaY;
|
||||||
// double dz = deltaZ < 360.0 / 2 ? deltaZ : 360.0 - deltaZ;
|
double dz = deltaZ < 360.0 / 2 ? deltaZ : 360.0 - deltaZ;
|
||||||
|
|
||||||
return Math.Sqrt((dx * dx) + (dy * dy) /*+ (dz * dz)*/);
|
return Math.Sqrt((dx * dx) + (dy * dy) /*+ (dz * dz)*/);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static double ViewAngleDistance(Vector3 a, Vector3 b, Vector3 c)
|
||||||
|
{
|
||||||
|
double dabX = Math.Abs(a.X - b.X);
|
||||||
|
dabX = dabX < 360.0 / 2 ? dabX : 360.0 - dabX;
|
||||||
|
double dabY = Math.Abs(a.Y - b.Y);
|
||||||
|
dabY = dabY < 360.0 / 2 ? dabY : 360.0 - dabY;
|
||||||
|
|
||||||
|
double dacX = Math.Abs(a.X - c.X);
|
||||||
|
dacX = dacX < 360.0 / 2 ? dacX : 360.0 - dacX;
|
||||||
|
double dacY = Math.Abs(a.Y - c.Y);
|
||||||
|
dacY = dacY < 360.0 / 2 ? dacY : 360.0 - dacY;
|
||||||
|
|
||||||
|
double dbcX = Math.Abs(b.X - c.X);
|
||||||
|
dbcX = dbcX < 360.0 / 2 ? dbcX : 360.0 - dbcX;
|
||||||
|
double dbcY = Math.Abs(b.Y - c.Y);
|
||||||
|
dbcY = dbcY < 360.0 / 2 ? dbcY : 360.0 - dbcY;
|
||||||
|
|
||||||
|
double deltaX = (dabX - dacX - dbcX) / 2.0;
|
||||||
|
deltaX = deltaX < 360.0 / 2 ? deltaX : 360.0 - deltaX;
|
||||||
|
double deltaY = (dabY - dacY - dbcY) / 2.0;
|
||||||
|
deltaY = deltaY < 360.0 / 2 ? deltaY : 360.0 - deltaY;
|
||||||
|
|
||||||
|
return Math.Round(Math.Sqrt((deltaX * deltaX) + (deltaY * deltaY)), 4);
|
||||||
|
}
|
||||||
|
|
||||||
public static Vector3 Subtract(Vector3 a, Vector3 b) => new Vector3(b.X - a.X, b.Y - a.Y, b.Z - a.Z);
|
public static Vector3 Subtract(Vector3 a, Vector3 b) => new Vector3(b.X - a.X, b.Y - a.Y, b.Z - a.Z);
|
||||||
|
|
||||||
public double DotProduct(Vector3 a) => (a.X * this.X) + (a.Y * this.Y) + (a.Z * this.Z);
|
public double DotProduct(Vector3 a) => (a.X * this.X) + (a.Y * this.Y) + (a.Z * this.Z);
|
||||||
|
@ -40,8 +40,14 @@ namespace SharedLibraryCore.Objects
|
|||||||
|
|
||||||
public async Task Tell(String Message)
|
public async Task Tell(String Message)
|
||||||
{
|
{
|
||||||
|
// this is console or remote so send immediately
|
||||||
|
if (ClientNumber < 0)
|
||||||
|
{
|
||||||
|
await CurrentServer.Tell(Message, this);
|
||||||
|
}
|
||||||
|
|
||||||
// await CurrentServer.Tell(Message, this);
|
else
|
||||||
|
{
|
||||||
var e = new GameEvent()
|
var e = new GameEvent()
|
||||||
{
|
{
|
||||||
Message = Message,
|
Message = Message,
|
||||||
@ -52,8 +58,7 @@ namespace SharedLibraryCore.Objects
|
|||||||
};
|
};
|
||||||
|
|
||||||
CurrentServer.Manager.GetEventHandler().AddEvent(e);
|
CurrentServer.Manager.GetEventHandler().AddEvent(e);
|
||||||
// this ensures the output it sent before returning
|
}
|
||||||
await Task.Run(() => e.OnProcessed.Wait());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Kick(String Message, Player Sender)
|
public async Task Kick(String Message, Player Sender)
|
||||||
|
@ -56,8 +56,6 @@ namespace SharedLibraryCore.RCon
|
|||||||
{
|
{
|
||||||
public IPEndPoint Endpoint { get; private set; }
|
public IPEndPoint Endpoint { get; private set; }
|
||||||
public string RConPassword { get; private set; }
|
public string RConPassword { get; private set; }
|
||||||
public ConcurrentQueue<ManualResetEventSlim> ResponseQueue;
|
|
||||||
//Socket ServerConnection;
|
|
||||||
ILogger Log;
|
ILogger Log;
|
||||||
int FailedSends;
|
int FailedSends;
|
||||||
int FailedReceives;
|
int FailedReceives;
|
||||||
@ -79,13 +77,6 @@ namespace SharedLibraryCore.RCon
|
|||||||
OnReceived = new ManualResetEvent(false);
|
OnReceived = new ManualResetEvent(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
~Connection()
|
|
||||||
{
|
|
||||||
/*ServerConnection.Shutdown(SocketShutdown.Both);
|
|
||||||
ServerConnection.Close();
|
|
||||||
ServerConnection.Dispose();*/
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnConnectedCallback(IAsyncResult ar)
|
private void OnConnectedCallback(IAsyncResult ar)
|
||||||
{
|
{
|
||||||
var serverSocket = (Socket)ar.AsyncState;
|
var serverSocket = (Socket)ar.AsyncState;
|
||||||
@ -144,12 +135,12 @@ namespace SharedLibraryCore.RCon
|
|||||||
if (!connectionState.Buffer.Take(4).ToArray().SequenceEqual(new byte[] { 0xFF, 0xFF, 0xFF, 0xFF }))
|
if (!connectionState.Buffer.Take(4).ToArray().SequenceEqual(new byte[] { 0xFF, 0xFF, 0xFF, 0xFF }))
|
||||||
throw new NetworkException("Unexpected packet received");
|
throw new NetworkException("Unexpected packet received");
|
||||||
|
|
||||||
if (FailedReceives == 0 && serverConnection.Available > 0)
|
/* if (FailedReceives == 0 && serverConnection.Available > 0)
|
||||||
{
|
{
|
||||||
serverConnection.BeginReceive(connectionState.Buffer, 0, connectionState.Buffer.Length, 0,
|
serverConnection.BeginReceive(connectionState.Buffer, 0, connectionState.Buffer.Length, 0,
|
||||||
new AsyncCallback(OnReceivedCallback), connectionState);
|
new AsyncCallback(OnReceivedCallback), connectionState);
|
||||||
}
|
}
|
||||||
else
|
else*/
|
||||||
{
|
{
|
||||||
response = connectionState.ResponseString.ToString();
|
response = connectionState.ResponseString.ToString();
|
||||||
OnReceived.Set();
|
OnReceived.Set();
|
||||||
@ -169,7 +160,7 @@ namespace SharedLibraryCore.RCon
|
|||||||
|
|
||||||
catch (ObjectDisposedException)
|
catch (ObjectDisposedException)
|
||||||
{
|
{
|
||||||
Log.WriteWarning($"Tried to check for more available bytes for disposed socket on {Endpoint}");
|
// Log.WriteWarning($"Tried to check for more available bytes for disposed socket on {Endpoint}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,7 +202,9 @@ namespace SharedLibraryCore.RCon
|
|||||||
retrySend:
|
retrySend:
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
Console.WriteLine($"Sending Command {parameters}");
|
||||||
|
#endif
|
||||||
if (!OnConnected.WaitOne(StaticHelpers.SocketTimeout))
|
if (!OnConnected.WaitOne(StaticHelpers.SocketTimeout))
|
||||||
throw new SocketException((int)SocketError.TimedOut);
|
throw new SocketException((int)SocketError.TimedOut);
|
||||||
|
|
||||||
|
@ -41,7 +41,6 @@ namespace SharedLibraryCore
|
|||||||
PlayerHistory = new Queue<PlayerHistory>();
|
PlayerHistory = new Queue<PlayerHistory>();
|
||||||
ChatHistory = new List<ChatInfo>();
|
ChatHistory = new List<ChatInfo>();
|
||||||
NextMessage = 0;
|
NextMessage = 0;
|
||||||
OnEvent = new ManualResetEventSlim();
|
|
||||||
CustomSayEnabled = Manager.GetApplicationSettings().Configuration().EnableCustomSayName;
|
CustomSayEnabled = Manager.GetApplicationSettings().Configuration().EnableCustomSayName;
|
||||||
CustomSayName = Manager.GetApplicationSettings().Configuration().CustomSayName;
|
CustomSayName = Manager.GetApplicationSettings().Configuration().CustomSayName;
|
||||||
InitializeTokens();
|
InitializeTokens();
|
||||||
@ -139,8 +138,8 @@ namespace SharedLibraryCore
|
|||||||
Manager.GetEventHandler().AddEvent(e);
|
Manager.GetEventHandler().AddEvent(e);
|
||||||
#else
|
#else
|
||||||
Logger.WriteVerbose(Message.StripColors());
|
Logger.WriteVerbose(Message.StripColors());
|
||||||
await Task.CompletedTask;
|
|
||||||
#endif
|
#endif
|
||||||
|
await Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -162,19 +161,22 @@ namespace SharedLibraryCore
|
|||||||
if (Target.Level == Player.Permission.Console)
|
if (Target.Level == Player.Permission.Console)
|
||||||
{
|
{
|
||||||
Console.ForegroundColor = ConsoleColor.Cyan;
|
Console.ForegroundColor = ConsoleColor.Cyan;
|
||||||
Console.WriteLine(Utilities.StripColors(Message));
|
Console.WriteLine(Message.StripColors());
|
||||||
Console.ForegroundColor = ConsoleColor.Gray;
|
Console.ForegroundColor = ConsoleColor.Gray;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CommandResult.Count > 15)
|
if (CommandResult.Count > 15)
|
||||||
CommandResult.RemoveAt(0);
|
CommandResult.RemoveAt(0);
|
||||||
|
|
||||||
|
if (Target.ClientNumber < 0)
|
||||||
|
{
|
||||||
CommandResult.Add(new CommandResponseInfo()
|
CommandResult.Add(new CommandResponseInfo()
|
||||||
{
|
{
|
||||||
Response = Utilities.StripColors(Message),
|
Response = Message.StripColors(),
|
||||||
ClientId = Target.ClientId
|
ClientId = Target.ClientId
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Send a message to all admins on the server
|
/// Send a message to all admins on the server
|
||||||
@ -315,7 +317,6 @@ namespace SharedLibraryCore
|
|||||||
public RCon.Connection RemoteConnection { get; protected set; }
|
public RCon.Connection RemoteConnection { get; protected set; }
|
||||||
public IRConParser RconParser { get; protected set; }
|
public IRConParser RconParser { get; protected set; }
|
||||||
public IEventParser EventParser { get; set; }
|
public IEventParser EventParser { get; set; }
|
||||||
public ManualResetEventSlim OnEvent { get; private set; }
|
|
||||||
|
|
||||||
// Internal
|
// Internal
|
||||||
protected string IP;
|
protected string IP;
|
||||||
@ -327,6 +328,7 @@ namespace SharedLibraryCore
|
|||||||
protected TimeSpan LastMessage;
|
protected TimeSpan LastMessage;
|
||||||
protected IFile LogFile;
|
protected IFile LogFile;
|
||||||
protected DateTime LastPoll;
|
protected DateTime LastPoll;
|
||||||
|
protected ManualResetEventSlim OnRemoteCommandResponse;
|
||||||
|
|
||||||
// only here for performance
|
// only here for performance
|
||||||
private bool CustomSayEnabled;
|
private bool CustomSayEnabled;
|
||||||
|
@ -407,7 +407,7 @@ namespace SharedLibraryCore
|
|||||||
|
|
||||||
public static Task SetDvarAsync(this Server server, string dvarName, object dvarValue) => server.RconParser.SetDvarAsync(server.RemoteConnection, dvarName, dvarValue);
|
public static Task SetDvarAsync(this Server server, string dvarName, object dvarValue) => server.RconParser.SetDvarAsync(server.RemoteConnection, dvarName, dvarValue);
|
||||||
|
|
||||||
public static Task<string[]> ExecuteCommandAsync(this Server server, string commandName) => server.RconParser.ExecuteCommandAsync(server.RemoteConnection, commandName);
|
public static async Task<string[]> ExecuteCommandAsync(this Server server, string commandName) => await server.RconParser.ExecuteCommandAsync(server.RemoteConnection, commandName);
|
||||||
|
|
||||||
public static Task<List<Player>> GetStatusAsync(this Server server) => server.RconParser.GetStatusAsync(server.RemoteConnection);
|
public static Task<List<Player>> GetStatusAsync(this Server server) => server.RconParser.GetStatusAsync(server.RemoteConnection);
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ namespace WebfrontCore.Controllers
|
|||||||
|
|
||||||
var remoteEvent = new GameEvent()
|
var remoteEvent = new GameEvent()
|
||||||
{
|
{
|
||||||
Type = GameEvent.EventType.Say,
|
Type = GameEvent.EventType.Command,
|
||||||
Data = command,
|
Data = command,
|
||||||
Origin = client,
|
Origin = client,
|
||||||
Owner = server,
|
Owner = server,
|
||||||
@ -48,8 +48,7 @@ namespace WebfrontCore.Controllers
|
|||||||
|
|
||||||
Manager.GetEventHandler().AddEvent(remoteEvent);
|
Manager.GetEventHandler().AddEvent(remoteEvent);
|
||||||
// wait for the event to process
|
// wait for the event to process
|
||||||
|
await Task.Run(() => remoteEvent.OnProcessed.Wait(5000));
|
||||||
await Task.Run(() => remoteEvent.OnProcessed.Wait());
|
|
||||||
var response = server.CommandResult.Where(c => c.ClientId == client.ClientId).ToList();
|
var response = server.CommandResult.Where(c => c.ClientId == client.ClientId).ToList();
|
||||||
|
|
||||||
// remove the added command response
|
// remove the added command response
|
||||||
|
@ -45,7 +45,7 @@
|
|||||||
|
|
||||||
<div id="profile_aliases" class="pr-0 pr-sm-4 pb-2 mb-2 text-muted order-0">
|
<div id="profile_aliases" class="pr-0 pr-sm-4 pb-2 mb-2 text-muted order-0">
|
||||||
@{
|
@{
|
||||||
@Model.NetworkId.ToString("X") <br/>
|
<span class="text-secondary">@Model.NetworkId.ToString("X")</span> <br />
|
||||||
foreach (string alias in Model.Aliases)
|
foreach (string alias in Model.Aliases)
|
||||||
{
|
{
|
||||||
@alias <br />
|
@alias <br />
|
||||||
|
Loading…
Reference in New Issue
Block a user