diff --git a/Application/Application.csproj b/Application/Application.csproj
index e9e42a771..364bd0e4d 100644
--- a/Application/Application.csproj
+++ b/Application/Application.csproj
@@ -32,7 +32,7 @@
true
true
- 2.2.7.6
+ 2.2.7.7
2.2.7.7
7.1
diff --git a/Application/IO/GameLogEventDetection.cs b/Application/IO/GameLogEventDetection.cs
index 35cb588f3..a23ce5fa1 100644
--- a/Application/IO/GameLogEventDetection.cs
+++ b/Application/IO/GameLogEventDetection.cs
@@ -30,7 +30,9 @@ namespace IW4MAdmin.Application.IO
{
while (!_server.Manager.CancellationToken.IsCancellationRequested)
{
+#if !DEBUG
if (_server.IsInitialized)
+#endif
{
try
{
diff --git a/Application/IW4MServer.cs b/Application/IW4MServer.cs
index 1d39ab9e1..ef43d3ccd 100644
--- a/Application/IW4MServer.cs
+++ b/Application/IW4MServer.cs
@@ -585,6 +585,13 @@ namespace IW4MAdmin
try
{
+#if DEBUG
+ if (Manager.GetApplicationSettings().Configuration().RConPollRate == int.MaxValue)
+ {
+ return true;
+ }
+#endif
+
var polledClients = await PollPlayersAsync();
var waiterList = new List();
@@ -766,7 +773,8 @@ namespace IW4MAdmin
if (version?.Value?.Length != 0)
{
- RconParser = Manager.AdditionalRConParsers.FirstOrDefault(_parser => _parser.Version == version.Value) ?? RconParser;
+ var matchedRconParser = Manager.AdditionalRConParsers.FirstOrDefault(_parser => _parser.Version == version.Value);
+ RconParser.Configuration = matchedRconParser != null ? matchedRconParser.Configuration : RconParser.Configuration;
EventParser = Manager.AdditionalEventParsers.FirstOrDefault(_parser => _parser.Version == version.Value) ?? EventParser;
Version = RconParser.Version;
}
@@ -1011,11 +1019,9 @@ namespace IW4MAdmin
#endif
}
- // this should link evading clients
if (isEvade)
{
Logger.WriteInfo($"updating alias for banned client {targetClient}");
- await Manager.GetClientService().UpdateAlias(targetClient);
}
EFPenalty newPenalty = new EFPenalty()
diff --git a/Application/Misc/Logger.cs b/Application/Misc/Logger.cs
index 8b4cc9462..69e7dd94c 100644
--- a/Application/Misc/Logger.cs
+++ b/Application/Misc/Logger.cs
@@ -1,6 +1,7 @@
using SharedLibraryCore;
using SharedLibraryCore.Interfaces;
using System;
+using System.Diagnostics;
using System.IO;
using System.Threading;
@@ -73,10 +74,12 @@ namespace IW4MAdmin.Application
// lets keep it simple and dispose of everything quickly as logging wont be that much (relatively)
Console.WriteLine(LogLine);
File.AppendAllText(FileName, LogLine + Environment.NewLine);
+ Debug.WriteLine(msg);
#else
if (type == LogType.Error || type == LogType.Verbose)
+ {
Console.WriteLine(LogLine);
- //if (type != LogType.Debug)
+ }
File.AppendAllText(FileName, $"{LogLine}{Environment.NewLine}");
#endif
}
diff --git a/Application/RconParsers/BaseRConParser.cs b/Application/RconParsers/BaseRConParser.cs
index 04a1abc9b..8a5ac2bb6 100644
--- a/Application/RconParsers/BaseRConParser.cs
+++ b/Application/RconParsers/BaseRConParser.cs
@@ -12,7 +12,11 @@ using static SharedLibraryCore.Server;
namespace IW4MAdmin.Application.RconParsers
{
+#if DEBUG
+ public class BaseRConParser : IRConParser
+#else
class BaseRConParser : IRConParser
+#endif
{
public BaseRConParser()
{
@@ -52,7 +56,7 @@ namespace IW4MAdmin.Application.RconParsers
public IRConParserConfiguration Configuration { get; set; }
- public string Version { get; set; } = "CoD";
+ public virtual string Version { get; set; } = "CoD";
public Game GameName { get; set; } = Game.COD;
public bool CanGenerateLogPath { get; set; } = true;
@@ -89,7 +93,7 @@ namespace IW4MAdmin.Application.RconParsers
};
}
- public async Task> GetStatusAsync(Connection connection)
+ public virtual async Task> GetStatusAsync(Connection connection)
{
string[] response = await connection.SendQueryAsync(StaticHelpers.QueryType.COMMAND_STATUS);
return ClientsFromStatus(response);
diff --git a/IW4MAdmin.sln b/IW4MAdmin.sln
index b96653921..84a779ef0 100644
--- a/IW4MAdmin.sln
+++ b/IW4MAdmin.sln
@@ -34,8 +34,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests", "Plugins\Tests\Test
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IW4ScriptCommands", "Plugins\IW4ScriptCommands\IW4ScriptCommands.csproj", "{6C706CE5-A206-4E46-8712-F8C48D526091}"
EndProject
-Project("{888888A0-9F3D-457C-B088-3A5042F75D52}") = "DiscordWebhook", "DiscordWebhook\DiscordWebhook.pyproj", "{15A81D6E-7502-46CE-8530-0647A380B5F4}"
-EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ScriptPlugins", "ScriptPlugins", "{3F9ACC27-26DB-49FA-BCD2-50C54A49C9FA}"
ProjectSection(SolutionItems) = preProject
Plugins\ScriptPlugins\ParserCoD4x.js = Plugins\ScriptPlugins\ParserCoD4x.js
@@ -309,18 +307,6 @@ Global
{6C706CE5-A206-4E46-8712-F8C48D526091}.Release|x64.Build.0 = Release|Any CPU
{6C706CE5-A206-4E46-8712-F8C48D526091}.Release|x86.ActiveCfg = Release|Any CPU
{6C706CE5-A206-4E46-8712-F8C48D526091}.Release|x86.Build.0 = Release|Any CPU
- {15A81D6E-7502-46CE-8530-0647A380B5F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {15A81D6E-7502-46CE-8530-0647A380B5F4}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {15A81D6E-7502-46CE-8530-0647A380B5F4}.Debug|x64.ActiveCfg = Debug|Any CPU
- {15A81D6E-7502-46CE-8530-0647A380B5F4}.Debug|x86.ActiveCfg = Debug|Any CPU
- {15A81D6E-7502-46CE-8530-0647A380B5F4}.Prerelease|Any CPU.ActiveCfg = Prerelease|Any CPU
- {15A81D6E-7502-46CE-8530-0647A380B5F4}.Prerelease|Mixed Platforms.ActiveCfg = Release|Any CPU
- {15A81D6E-7502-46CE-8530-0647A380B5F4}.Prerelease|x64.ActiveCfg = Release|Any CPU
- {15A81D6E-7502-46CE-8530-0647A380B5F4}.Prerelease|x86.ActiveCfg = Release|Any CPU
- {15A81D6E-7502-46CE-8530-0647A380B5F4}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {15A81D6E-7502-46CE-8530-0647A380B5F4}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
- {15A81D6E-7502-46CE-8530-0647A380B5F4}.Release|x64.ActiveCfg = Release|Any CPU
- {15A81D6E-7502-46CE-8530-0647A380B5F4}.Release|x86.ActiveCfg = Release|Any CPU
{42EFDA12-10D3-4C40-A210-9483520116BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{42EFDA12-10D3-4C40-A210-9483520116BC}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{42EFDA12-10D3-4C40-A210-9483520116BC}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
diff --git a/Plugins/Stats/Cheat/Detection.cs b/Plugins/Stats/Cheat/Detection.cs
index 4d5817666..d7b9f2aff 100644
--- a/Plugins/Stats/Cheat/Detection.cs
+++ b/Plugins/Stats/Cheat/Detection.cs
@@ -133,6 +133,8 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
var weightedSessionAverage = HitLocationCount.Where(_hit => _hit.Value.Count > 0)
.Sum(_hit => _hit.Value.Offset * _hit.Value.Count) / totalSessionHits;
+ AngleDifferenceAverage = weightedSessionAverage;
+
if (weightedSessionAverage > Thresholds.MaxOffset(totalSessionHits) &&
totalSessionHits > 40)
{
diff --git a/Plugins/Tests/ClientTests.cs b/Plugins/Tests/ClientTests.cs
index efcea2b0e..597a3bcbb 100644
--- a/Plugins/Tests/ClientTests.cs
+++ b/Plugins/Tests/ClientTests.cs
@@ -2,11 +2,13 @@
using SharedLibraryCore;
using SharedLibraryCore.Commands;
using SharedLibraryCore.Database.Models;
+using SharedLibraryCore.Events;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
+using System.Threading.Tasks;
using Xunit;
namespace Tests
@@ -14,12 +16,12 @@ namespace Tests
[Collection("ManagerCollection")]
public class ClientTests
{
- readonly ApplicationManager Manager;
+ private readonly ApplicationManager _manager;
const int TestTimeout = 10000;
public ClientTests(ManagerFixture fixture)
{
- Manager = fixture.Manager;
+ _manager = fixture.Manager;
}
[Fact]
@@ -41,38 +43,122 @@ namespace Tests
}
[Fact]
- public void WarnClientShouldSucceed()
+ public void BanEvasionShouldLink()
{
- while (!Manager.IsInitialized)
+ var server = _manager.Servers[0];
+ var waiter = new ManualResetEventSlim();
+
+ _manager.GetApplicationSettings().Configuration().RConPollRate = 5000;
+
+
+ while (!server.IsInitialized)
{
Thread.Sleep(100);
}
- var client = Manager.Servers.First().GetClientsAsList().FirstOrDefault();
+ var e = new GameEvent()
+ {
+ Type = GameEvent.EventType.PreConnect,
+ Owner = server,
+ Origin = new EFClient()
+ {
+ NetworkId = 1337,
+ ClientNumber = 0,
+ CurrentAlias = new EFAlias()
+ {
+ Name = "Ban Me",
+ IPAddress = 1337
+ }
+ }
+ };
- Assert.False(client == null, "no client found to warn");
+ _manager.GetEventHandler().AddEvent(e);
+ e.OnProcessed.Wait();
- var warnEvent = client.Warn("test warn", new EFClient() { ClientId = 1, Level = EFClient.Permission.Console, CurrentServer = client.CurrentServer });
- warnEvent.OnProcessed.Wait();
+ e = new GameEvent()
+ {
+ Type = GameEvent.EventType.PreConnect,
+ Owner = server,
+ Origin = new EFClient()
+ {
+ NetworkId = 1338,
+ ClientNumber = 1,
+ CurrentAlias = new EFAlias()
+ {
+ Name = "Ban Me",
+ IPAddress = null
+ }
+ }
+ };
- //Assert.True((client.Warnings == 1 ||
- // warnEvent.Failed) &&
- // Manager.GetPenaltyService().GetClientPenaltiesAsync(client.ClientId).Result.Count(p => p.Type == Penalty.PenaltyType.Warning) == 1,
- // "warning did not get applied");
+ _manager.GetEventHandler().AddEvent(e);
+ e.OnProcessed.Wait();
+
+ e = new GameEvent()
+ {
+ Type = GameEvent.EventType.Update,
+ Owner = server,
+ Origin = new EFClient()
+ {
+ NetworkId = 1338,
+ ClientNumber = 1,
+ CurrentAlias = new EFAlias()
+ {
+ Name = "Ban Me",
+ IPAddress = 1337
+ }
+ }
+ };
+
+ _manager.GetEventHandler().AddEvent(e);
+ e.OnProcessed.Wait();
+
+ }
+
+ [Fact]
+ public void WarnClientShouldSucceed()
+ {
+ var onJoined = new ManualResetEventSlim();
+ var server = _manager.Servers[0];
+
+ while (!server.IsInitialized)
+ {
+ Thread.Sleep(100);
+ }
+
+ _manager.OnServerEvent += (sender, eventArgs) =>
+ {
+ if (eventArgs.Event.Type == GameEvent.EventType.Connect)
+ {
+ onJoined.Set();
+ }
+ };
+
+ server.EmulateClientJoinLog();
+ onJoined.Wait();
+
+ var client = server.Clients[0];
+
+ var warnEvent = client.Warn("test warn", Utilities.IW4MAdminClient(server));
+ warnEvent.OnProcessed.Wait(5000);
+
+ Assert.False(warnEvent.Failed);
warnEvent = client.Warn("test warn", new EFClient() { ClientId = 1, Level = EFClient.Permission.Banned, CurrentServer = client.CurrentServer });
- warnEvent.OnProcessed.Wait();
+ warnEvent.OnProcessed.Wait(5000);
Assert.True(warnEvent.FailReason == GameEvent.EventFailReason.Permission &&
client.Warnings == 1, "warning was applied without proper permissions");
// warn clear
var warnClearEvent = client.WarnClear(new EFClient { ClientId = 1, Level = EFClient.Permission.Banned, CurrentServer = client.CurrentServer });
+ warnClearEvent.OnProcessed.Wait(5000);
Assert.True(warnClearEvent.FailReason == GameEvent.EventFailReason.Permission &&
client.Warnings == 1, "warning was removed without proper permissions");
- warnClearEvent = client.WarnClear(new EFClient { ClientId = 1, Level = EFClient.Permission.Console, CurrentServer = client.CurrentServer });
+ warnClearEvent = client.WarnClear(Utilities.IW4MAdminClient(server));
+ warnClearEvent.OnProcessed.Wait(5000);
Assert.True(!warnClearEvent.Failed && client.Warnings == 0, "warning was not cleared");
}
@@ -80,12 +166,12 @@ namespace Tests
[Fact]
public void ReportClientShouldSucceed()
{
- while (!Manager.IsInitialized)
+ while (!_manager.IsInitialized)
{
Thread.Sleep(100);
}
- var client = Manager.Servers.First().GetClientsAsList().FirstOrDefault();
+ var client = _manager.Servers.First().GetClientsAsList().FirstOrDefault();
Assert.False(client == null, "no client found to report");
// fail
@@ -127,12 +213,12 @@ namespace Tests
[Fact]
public void FlagClientShouldSucceed()
{
- while (!Manager.IsInitialized)
+ while (!_manager.IsInitialized)
{
Thread.Sleep(100);
}
- var client = Manager.Servers.First().GetClientsAsList().FirstOrDefault();
+ var client = _manager.Servers.First().GetClientsAsList().FirstOrDefault();
Assert.False(client == null, "no client found to flag");
var flagEvent = client.Flag("test flag", new EFClient { ClientId = 1, Level = EFClient.Permission.Console, CurrentServer = client.CurrentServer });
@@ -177,12 +263,12 @@ namespace Tests
[Fact]
void KickClientShouldSucceed()
{
- while (!Manager.IsInitialized)
+ while (!_manager.IsInitialized)
{
Thread.Sleep(100);
}
- var client = Manager.Servers.First().GetClientsAsList().FirstOrDefault();
+ var client = _manager.Servers.First().GetClientsAsList().FirstOrDefault();
Assert.False(client == null, "no client found to kick");
var kickEvent = client.Kick("test kick", new EFClient() { ClientId = 1, Level = EFClient.Permission.Banned, CurrentServer = client.CurrentServer });
@@ -193,18 +279,18 @@ namespace Tests
kickEvent = client.Kick("test kick", new EFClient() { ClientId = 1, Level = EFClient.Permission.Console, CurrentServer = client.CurrentServer });
kickEvent.OnProcessed.Wait();
- Assert.True(Manager.Servers.First().GetClientsAsList().FirstOrDefault(c => c.NetworkId == client.NetworkId) == null, "client was not kicked");
+ Assert.True(_manager.Servers.First().GetClientsAsList().FirstOrDefault(c => c.NetworkId == client.NetworkId) == null, "client was not kicked");
}
[Fact]
void TempBanClientShouldSucceed()
{
- while (!Manager.IsInitialized)
+ while (!_manager.IsInitialized)
{
Thread.Sleep(100);
}
- var client = Manager.Servers.First().GetClientsAsList().FirstOrDefault();
+ var client = _manager.Servers.First().GetClientsAsList().FirstOrDefault();
Assert.False(client == null, "no client found to tempban");
var tbCommand = new CTempBan();
@@ -217,19 +303,19 @@ namespace Tests
Owner = client.CurrentServer
}).Wait();
- Assert.True(Manager.GetPenaltyService().GetActivePenaltiesAsync(client.AliasLinkId).Result.Count(p => p.Type == EFPenalty.PenaltyType.TempBan) == 1,
+ Assert.True(_manager.GetPenaltyService().GetActivePenaltiesAsync(client.AliasLinkId).Result.Count(p => p.Type == EFPenalty.PenaltyType.TempBan) == 1,
"tempban was not added");
}
[Fact]
void BanUnbanClientShouldSucceed()
{
- while (!Manager.IsInitialized)
+ while (!_manager.IsInitialized)
{
Thread.Sleep(100);
}
- var client = Manager.Servers.First().GetClientsAsList().FirstOrDefault();
+ var client = _manager.Servers.First().GetClientsAsList().FirstOrDefault();
Assert.False(client == null, "no client found to ban");
var banCommand = new CBan();
@@ -242,7 +328,7 @@ namespace Tests
Owner = client.CurrentServer
}).Wait();
- Assert.True(Manager.GetPenaltyService().GetActivePenaltiesAsync(client.AliasLinkId).Result.Count(p => p.Type == EFPenalty.PenaltyType.Ban) == 1,
+ Assert.True(_manager.GetPenaltyService().GetActivePenaltiesAsync(client.AliasLinkId).Result.Count(p => p.Type == EFPenalty.PenaltyType.Ban) == 1,
"ban was not added");
var unbanCommand = new CUnban();
@@ -255,7 +341,7 @@ namespace Tests
Owner = client.CurrentServer
}).Wait();
- Assert.True(Manager.GetPenaltyService().GetActivePenaltiesAsync(client.AliasLinkId).Result.Count(p => p.Type == EFPenalty.PenaltyType.Ban) == 0,
+ Assert.True(_manager.GetPenaltyService().GetActivePenaltiesAsync(client.AliasLinkId).Result.Count(p => p.Type == EFPenalty.PenaltyType.Ban) == 0,
"ban was not removed");
}
diff --git a/Plugins/Tests/ManagerFixture.cs b/Plugins/Tests/ManagerFixture.cs
index 69ab998d2..824e46df2 100644
--- a/Plugins/Tests/ManagerFixture.cs
+++ b/Plugins/Tests/ManagerFixture.cs
@@ -16,9 +16,9 @@ namespace Tests
public ManagerFixture()
{
- File.WriteAllText("test_mp.log", "test_log_file");
+ string logFile = @"X:\IW4MAdmin\Plugins\Tests\bin\Debug\netcoreapp2.2\test_mp.log";
- //IW4MAdmin.Application.Localization.Configure.Initialize("en-US");
+ File.WriteAllText(logFile, Environment.NewLine);
Manager = ApplicationManager.GetInstance();
@@ -31,18 +31,22 @@ namespace Tests
AutoMessages = new List(),
IPAddress = "127.0.0.1",
Password = "test",
- Port = 28963,
+ Port = 28960,
Rules = new List(),
- ManualLogPath = "http://google.com"
+ RConParserVersion = "test",
+ EventParserVersion = "IW4x (v0.6.0)",
+ ManualLogPath = logFile
}
},
AutoMessages = new List(),
GlobalRules = new List(),
Maps = new List(),
- RConPollRate = 10000
+ RConPollRate = int.MaxValue
};
+
Manager.ConfigHandler = new BaseConfigurationHandler("test");
Manager.ConfigHandler.Set(config);
+ Manager.AdditionalRConParsers.Add(new TestRconParser());
Manager.Init().Wait();
diff --git a/Plugins/Tests/ManagerTests.cs b/Plugins/Tests/ManagerTests.cs
index 8f6372bae..807f38602 100644
--- a/Plugins/Tests/ManagerTests.cs
+++ b/Plugins/Tests/ManagerTests.cs
@@ -1,7 +1,6 @@
using IW4MAdmin.Application;
using SharedLibraryCore;
using SharedLibraryCore.Database.Models;
-using SharedLibraryCore.Interfaces;
using System;
using System.Collections.Generic;
using System.Diagnostics;
@@ -33,162 +32,17 @@ namespace Tests
[Fact]
public void AreCommandAliasesUnique()
{
- var mgr = Program.ServerManager;
+ var mgr = Manager;
bool test = mgr.GetCommands().Count == mgr.GetCommands().Select(c => c.Alias).Distinct().Count();
+ foreach (var duplicate in mgr.GetCommands().GroupBy(_cmd => _cmd.Alias).Where(_grp => _grp.Count() > 1).Select(_grp => new { Command = _grp.First().Name, Alias = _grp.Key }))
+ {
+ Debug.WriteLine($"{duplicate.Command}: {duplicate.Alias}");
+ }
+
Assert.True(test, "command aliases are not unique");
}
- [Fact]
- public void AddAndRemoveClientsViaJoinShouldSucceed()
- {
- var server = Manager.GetServers().First();
- var waiters = new Queue();
-
- int clientStartIndex = 4;
- int clientNum = 10;
-
- for (int i = clientStartIndex; i < clientStartIndex + clientNum; i++)
- {
- var e = new GameEvent()
- {
- Type = GameEvent.EventType.Join,
- Origin = new EFClient()
- {
- Name = $"Player{i}",
- NetworkId = i,
- ClientNumber = i - 1
- },
- Owner = server
- };
-
- server.Manager.GetEventHandler().AddEvent(e);
- waiters.Enqueue(e);
- }
-
- while (waiters.Count > 0)
- {
- waiters.Dequeue().OnProcessed.Wait();
- }
-
- Assert.True(server.ClientNum == clientNum, $"client num does not match added client num [{server.ClientNum}:{clientNum}]");
-
- for (int i = clientStartIndex; i < clientStartIndex + clientNum; i++)
- {
- var e = new GameEvent()
- {
- Type = GameEvent.EventType.Disconnect,
- Origin = new EFClient()
- {
- Name = $"Player{i}",
- NetworkId = i,
- ClientNumber = i - 1
- },
- Owner = server
- };
-
- server.Manager.GetEventHandler().AddEvent(e);
- waiters.Enqueue(e);
- }
-
- while (waiters.Count > 0)
- {
- waiters.Dequeue().OnProcessed.Wait();
- }
-
- Assert.True(server.ClientNum == 0, "there are still clients connected");
- }
-
- [Fact]
- public void AddAndRemoveClientsViaRconShouldSucceed()
- {
- var server = Manager.GetServers().First();
- var waiters = new Queue();
-
- int clientIndexStart = 1;
- int clientNum = 8;
-
- for (int i = clientIndexStart; i < clientNum + clientIndexStart; i++)
- {
- var e = new GameEvent()
- {
- Type = GameEvent.EventType.Connect,
- Origin = new EFClient()
- {
- Name = $"Player{i}",
- NetworkId = i,
- ClientNumber = i - 1,
- IPAddress = i,
- Ping = 50,
- CurrentServer = server
- },
- Owner = server,
- };
-
- Manager.GetEventHandler().AddEvent(e);
- waiters.Enqueue(e);
- }
-
- while (waiters.Count > 0)
- {
- waiters.Dequeue().OnProcessed.Wait();
- }
-
- int actualClientNum = server.GetClientsAsList().Count(p => p.State == EFClient.ClientState.Connected);
- Assert.True(actualClientNum == clientNum, $"client connected states don't match [{actualClientNum}:{clientNum}");
-
- for (int i = clientIndexStart; i < clientNum + clientIndexStart; i++)
- {
- var e = new GameEvent()
- {
- Type = GameEvent.EventType.Disconnect,
- Origin = new EFClient()
- {
- Name = $"Player{i}",
- NetworkId = i,
- ClientNumber = i - 1,
- IPAddress = i,
- Ping = 50,
- CurrentServer = server
- },
- Owner = server,
- };
-
- Manager.GetEventHandler().AddEvent(e);
- waiters.Enqueue(e);
- }
-
- while (waiters.Count > 0)
- {
- waiters.Dequeue().OnProcessed.Wait();
- }
-
- actualClientNum = server.ClientNum;
- Assert.True(actualClientNum == 0, "there are clients still connected");
- }
-
-
- [Fact]
- public void AddClientViaLog()
- {
- var resetEvent = new ManualResetEventSlim();
- resetEvent.Reset();
-
- Manager.OnServerEvent += (sender, eventArgs) =>
- {
- if (eventArgs.Event.Type == GameEvent.EventType.Join)
- {
- eventArgs.Event.OnProcessed.Wait();
- Assert.True(false);
- }
- };
-
- File.AppendAllText("test_mp.log", " 2:33 J;224b3d0bc64ab4f9;0;goober");
-
-
- resetEvent.Wait(5000);
- }
-
[Fact]
public void PrintCommands()
{
diff --git a/Plugins/Tests/ServerTests.cs b/Plugins/Tests/ServerTests.cs
index c62138f90..69c65932c 100644
--- a/Plugins/Tests/ServerTests.cs
+++ b/Plugins/Tests/ServerTests.cs
@@ -1,10 +1,113 @@
-using System;
+using IW4MAdmin.Application;
+using SharedLibraryCore;
+using System;
using System.Collections.Generic;
+using System.IO;
using System.Text;
+using System.Threading;
+using Xunit;
namespace Tests
{
- class ServerTests
+ [Collection("ManagerCollection")]
+ public class ServerTests
{
+ private readonly ApplicationManager _manager;
+
+ public ServerTests(ManagerFixture fixture)
+ {
+ _manager = fixture.Manager;
+ }
+
+ [Fact]
+ public void AddAndRemoveClientViaLog()
+ {
+ var resetEvent = new ManualResetEventSlim();
+ var server = _manager.Servers[0];
+
+ var currentClientCount = server.ClientNum;
+ int eventsProcessed = 0;
+
+ _manager.OnServerEvent += (sender, eventArgs) =>
+ {
+ if (eventArgs.Event.Type == GameEvent.EventType.Connect)
+ {
+ eventArgs.Event.OnProcessed.Wait();
+ Assert.False(eventArgs.Event.Failed, "connect event was not processed");
+ Assert.True(server.ClientNum == currentClientCount + 1, "client count was not incremented");
+ eventsProcessed++;
+ resetEvent.Set();
+ }
+
+ if (eventArgs.Event.Type == GameEvent.EventType.Disconnect)
+ {
+ eventArgs.Event.OnProcessed.Wait();
+ Assert.False(eventArgs.Event.Failed, "disconnect event was not processed");
+ Assert.True(server.ClientNum == currentClientCount, "client count was not decremented");
+ eventsProcessed++;
+ resetEvent.Set();
+ }
+ };
+
+ server.EmulateClientJoinLog();
+
+ resetEvent.Wait(15000);
+ resetEvent.Reset();
+
+ Assert.Equal(1, eventsProcessed);
+
+ server.EmulateClientQuitLog();
+
+ resetEvent.Wait(15000);
+
+ Assert.Equal(2, eventsProcessed);
+ }
+
+ [Fact]
+ public void AddAndRemoveClientViaRcon()
+ {
+ var resetEvent = new ManualResetEventSlim();
+ var server = _manager.Servers[0];
+
+ var currentClientCount = server.ClientNum;
+ int eventsProcessed = 0;
+
+ _manager.GetApplicationSettings().Configuration().RConPollRate = 5000;
+ _manager.OnServerEvent += (sender, eventArgs) =>
+ {
+ if (eventArgs.Event.Type == GameEvent.EventType.Connect)
+ {
+ eventArgs.Event.OnProcessed.Wait();
+ Assert.False(eventArgs.Event.Failed, "connect event was not processed");
+ Assert.True(server.ClientNum == currentClientCount + 1, "client count was not incremented");
+ eventsProcessed++;
+ resetEvent.Set();
+ }
+
+ if (eventArgs.Event.Type == GameEvent.EventType.Disconnect)
+ {
+ eventArgs.Event.OnProcessed.Wait();
+ Assert.False(eventArgs.Event.Failed, "disconnect event was not processed");
+ Assert.True(server.ClientNum == currentClientCount, "client count was not decremented");
+ eventsProcessed++;
+ resetEvent.Set();
+ }
+ };
+
+ (server.RconParser as TestRconParser).FakeClientCount = 1;
+
+ resetEvent.Wait(15000);
+ resetEvent.Reset();
+
+ Assert.Equal(1, eventsProcessed);
+
+ (server.RconParser as TestRconParser).FakeClientCount = 0;
+
+ resetEvent.Wait(15000);
+
+ Assert.Equal(2, eventsProcessed);
+
+ _manager.GetApplicationSettings().Configuration().RConPollRate = int.MaxValue;
+ }
}
}
diff --git a/Plugins/Tests/TestHelpers.cs b/Plugins/Tests/TestHelpers.cs
new file mode 100644
index 000000000..30d13ed7f
--- /dev/null
+++ b/Plugins/Tests/TestHelpers.cs
@@ -0,0 +1,24 @@
+using IW4MAdmin.Application;
+using SharedLibraryCore;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+
+namespace Tests
+{
+ internal static class TestHelpers
+ {
+ internal static void EmulateClientJoinLog(this Server svr)
+ {
+ long guid = svr.ClientNum + 1;
+ File.AppendAllText(svr.LogPath, $"0:00 J;{guid};{svr.ClientNum};test_client_{svr.ClientNum}\r\n");
+ }
+
+ internal static void EmulateClientQuitLog(this Server svr)
+ {
+ long guid = Math.Max(1, svr.ClientNum);
+ File.AppendAllText(svr.LogPath, $"0:00 Q;{guid};{svr.ClientNum};test_client_{svr.ClientNum}\r\n");
+ }
+ }
+}
diff --git a/Plugins/Tests/TestRconParser.cs b/Plugins/Tests/TestRconParser.cs
new file mode 100644
index 000000000..b1c6d8aba
--- /dev/null
+++ b/Plugins/Tests/TestRconParser.cs
@@ -0,0 +1,38 @@
+using SharedLibraryCore.Database.Models;
+using SharedLibraryCore.RCon;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tests
+{
+ class TestRconParser : IW4MAdmin.Application.RconParsers.BaseRConParser
+ {
+ public int FakeClientCount { get; set; }
+ public List FakeClients { get; set; } = new List();
+
+ public override string Version => "test";
+
+ public override async Task> GetStatusAsync(Connection connection)
+ {
+ var clientList = new List();
+
+ for (int i = 0; i < FakeClientCount; i++)
+ {
+ clientList.Add(new EFClient()
+ {
+ ClientNumber = i,
+ NetworkId = i + 1,
+ CurrentAlias = new EFAlias()
+ {
+ Name = $"test_bot_{i}",
+ IPAddress = i + 1
+ }
+ });
+ }
+
+ return clientList.Count > 0 ? clientList : FakeClients;
+ }
+ }
+}
diff --git a/SharedLibraryCore/Commands/NativeCommands.cs b/SharedLibraryCore/Commands/NativeCommands.cs
index 98f205dc8..8538d5e02 100644
--- a/SharedLibraryCore/Commands/NativeCommands.cs
+++ b/SharedLibraryCore/Commands/NativeCommands.cs
@@ -31,7 +31,7 @@ namespace SharedLibraryCore.Commands
public class CRestart : Command
{
public CRestart() :
- base("restart", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_RESTART_DESC"], "rs", EFClient.Permission.Owner, false)
+ base("restart", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_RESTART_DESC"], "res", EFClient.Permission.Owner, false)
{ }
public override Task ExecuteAsync(GameEvent E)
diff --git a/SharedLibraryCore/PartialEntities/EFClient.cs b/SharedLibraryCore/PartialEntities/EFClient.cs
index 19897d413..8ea67af22 100644
--- a/SharedLibraryCore/PartialEntities/EFClient.cs
+++ b/SharedLibraryCore/PartialEntities/EFClient.cs
@@ -205,12 +205,7 @@ namespace SharedLibraryCore.Database.Models
int reportCount = sender.GetAdditionalProperty("_reportCount");
- if (Level > sender.Level)
- {
- e.FailReason = GameEvent.EventFailReason.Permission;
- }
-
- else if (Equals(sender))
+ if (Equals(sender))
{
e.FailReason = GameEvent.EventFailReason.Invalid;
}
diff --git a/SharedLibraryCore/Services/ClientService.cs b/SharedLibraryCore/Services/ClientService.cs
index e3f31500e..2a739bba4 100644
--- a/SharedLibraryCore/Services/ClientService.cs
+++ b/SharedLibraryCore/Services/ClientService.cs
@@ -109,6 +109,20 @@ namespace SharedLibraryCore.Services
var aliasSql = iqAliases.ToSql();
#endif
var aliases = await iqAliases.ToListAsync();
+
+ // see if they have a matching IP + Name but new NetworkId
+ var existingExactAlias = aliases.FirstOrDefault(a => a.Name == name && a.IPAddress == ip);
+ bool hasExactAliasMatch = existingExactAlias != null;
+
+ // if existing alias matches link them
+ var newAliasLink = existingExactAlias?.Link;
+ // if no exact matches find the first IP or LinkId that matches
+ newAliasLink = newAliasLink ?? aliases.OrderBy(_alias => _alias.LinkId).FirstOrDefault()?.Link;
+ // if no matches are found, use our current one ( it will become permanent )
+ newAliasLink = newAliasLink ?? entity.AliasLink;
+
+ bool hasExistingAlias = aliases.Count > 0;
+ bool isAliasLinkUpdated = newAliasLink.AliasLinkId != entity.AliasLink.AliasLinkId;
// update each of the aliases where this is no IP but the name is identical
foreach (var alias in aliases.Where(_alias => (_alias.IPAddress == null || _alias.IPAddress == 0)))
@@ -118,20 +132,6 @@ namespace SharedLibraryCore.Services
await context.SaveChangesAsync();
- // see if they have a matching IP + Name but new NetworkId
- var existingExactAlias = aliases.FirstOrDefault(a => a.Name == name && a.IPAddress == ip);
- bool hasExactAliasMatch = existingExactAlias != null;
-
- // if existing alias matches link them
- var newAliasLink = existingExactAlias?.Link;
- // if no exact matches find the first IP or LinkId that matches
- newAliasLink = newAliasLink ?? aliases.FirstOrDefault()?.Link;
- // if no matches are found, use our current one ( it will become permanent )
- newAliasLink = newAliasLink ?? entity.AliasLink;
-
- bool hasExistingAlias = aliases.Count > 0;
- bool isAliasLinkUpdated = newAliasLink.AliasLinkId != entity.AliasLink.AliasLinkId;
-
// this happens when the link we found is different than the one we create before adding an IP
if (isAliasLinkUpdated)
{