allow enabling of only specific detection types

allow override of anticheat for tmw3
fix invalid cast if E.Extra is not a command
add a delay after map rotation before getting the the server info. (hopefully prevents increased lost connection notification frequency)
This commit is contained in:
RaidMax 2019-10-23 10:40:24 -05:00
parent 96e434213f
commit f31ce6b001
5 changed files with 51 additions and 20 deletions

View File

@ -148,12 +148,10 @@ namespace IW4MAdmin
} }
// hack: this prevents commands from getting executing that 'shouldn't' be // hack: this prevents commands from getting executing that 'shouldn't' be
if (E.Type == GameEvent.EventType.Command && if (E.Type == GameEvent.EventType.Command && E.Extra is Command command &&
E.Extra != null && (canExecuteCommand || E.Origin?.Level == Permission.Console))
(canExecuteCommand ||
E.Origin?.Level == EFClient.Permission.Console))
{ {
await (((Command)E.Extra).ExecuteAsync(E)); await command.ExecuteAsync(E);
} }
} }
@ -444,7 +442,7 @@ namespace IW4MAdmin
// iw4 doesn't log the game info // iw4 doesn't log the game info
if (E.Extra == null) if (E.Extra == null)
{ {
var dict = await this.GetInfoAsync(); var dict = await this.GetInfoAsync(new TimeSpan(0, 0, 20));
if (dict == null) if (dict == null)
{ {

View File

@ -15,6 +15,7 @@ namespace IW4MAdmin.Plugins.Stats.Config
public int TopPlayersMinPlayTime { get; set; } public int TopPlayersMinPlayTime { get; set; }
public bool StoreClientKills { get; set; } public bool StoreClientKills { get; set; }
public IDictionary<DetectionType, DistributionConfiguration> DetectionDistributions { get; set; } public IDictionary<DetectionType, DistributionConfiguration> DetectionDistributions { get; set; }
public IDictionary<long, DetectionType[]> ServerDetectionTypes { get; set; }
public string Name() => "Stats"; public string Name() => "Stats";
public IBaseConfiguration Generate() public IBaseConfiguration Generate()

View File

@ -14,6 +14,7 @@ using System.Linq;
using System.Linq.Expressions; using System.Linq.Expressions;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using static IW4MAdmin.Plugins.Stats.Cheat.Detection;
namespace IW4MAdmin.Plugins.Stats.Helpers namespace IW4MAdmin.Plugins.Stats.Helpers
{ {
@ -566,8 +567,31 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
} }
} }
private bool ShouldUseDetection(long serverId, DetectionType detectionType)
{
var detectionTypes = Plugin.Config.Configuration().ServerDetectionTypes;
if (detectionTypes == null)
{
return true;
}
if (!detectionTypes.ContainsKey(serverId))
{
return true;
}
return detectionTypes[serverId].Contains(detectionType);
}
async Task ApplyPenalty(DetectionPenaltyResult penalty, EFClient attacker) async Task ApplyPenalty(DetectionPenaltyResult penalty, EFClient attacker)
{ {
// allow disabling of certain detection types
if (!ShouldUseDetection(attacker.CurrentServer.EndPoint, penalty.Type))
{
return;
}
var penaltyClient = Utilities.IW4MAdminClient(attacker.CurrentServer); var penaltyClient = Utilities.IW4MAdminClient(attacker.CurrentServer);
switch (penalty.ClientPenalty) switch (penalty.ClientPenalty)
{ {

View File

@ -82,7 +82,7 @@ namespace IW4MAdmin.Plugins.Stats
break; break;
case GameEvent.EventType.ScriptKill: case GameEvent.EventType.ScriptKill:
string[] killInfo = (E.Data != null) ? E.Data.Split(';') : new string[0]; string[] killInfo = (E.Data != null) ? E.Data.Split(';') : new string[0];
if (E.Owner.CustomCallback && killInfo.Length >= 14 && !ShouldIgnoreEvent(E.Origin, E.Target)) if ((E.Owner.CustomCallback || ShouldOverrideAnticheatSetting(E.Owner)) && killInfo.Length >= 14 && !ShouldIgnoreEvent(E.Origin, E.Target))
{ {
// this treats "world" damage as self damage // this treats "world" damage as self damage
if (IsWorldDamage(E.Origin)) if (IsWorldDamage(E.Origin))
@ -129,7 +129,7 @@ namespace IW4MAdmin.Plugins.Stats
break; 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 (E.Owner.CustomCallback && killInfo.Length >= 14 && !ShouldIgnoreEvent(E.Origin, E.Target)) if ((E.Owner.CustomCallback || ShouldOverrideAnticheatSetting(E.Owner)) && killInfo.Length >= 14 && !ShouldIgnoreEvent(E.Origin, E.Target))
{ {
// this treats "world" damage as self damage // this treats "world" damage as self damage
if (IsWorldDamage(E.Origin)) if (IsWorldDamage(E.Origin))
@ -515,5 +515,12 @@ namespace IW4MAdmin.Plugins.Stats
/// <param name="origin"></param> /// <param name="origin"></param>
/// <returns></returns> /// <returns></returns>
private bool IsWorldDamage(EFClient origin) => origin?.NetworkId == 1; private bool IsWorldDamage(EFClient origin) => origin?.NetworkId == 1;
/// <summary>
/// Indicates if we should try to use anticheat even if sv_customcallbacks is not defined
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
private bool ShouldOverrideAnticheatSetting(Server s) => Config.Configuration().EnableAntiCheat && s.GameName == Server.Game.IW5;
} }
} }

View File

@ -723,19 +723,20 @@ namespace SharedLibraryCore
return server.RconParser.GetStatusAsync(server.RemoteConnection); return server.RconParser.GetStatusAsync(server.RemoteConnection);
} }
public static async Task<Dictionary<string, string>> GetInfoAsync(this Server server) /// <summary>
/// Retrieves the key value pairs for server information usually checked after map rotation
/// </summary>
/// <param name="server"></param>
/// <param name="delay">How long to wait after the map has rotated to query</param>
/// <returns></returns>
public static async Task<IDictionary<string, string>> GetInfoAsync(this Server server, TimeSpan? delay = null)
{ {
string[] response = new string[0]; if (delay != null)
for (int i = 0; i < 4; i++)
{ {
response = await server.RemoteConnection.SendQueryAsync(RCon.StaticHelpers.QueryType.GET_INFO); await Task.Delay(delay.Value);
if (response.Length == 2)
{
break;
}
await Task.Delay(RCon.StaticHelpers.FloodProtectionInterval);
} }
var response = await server.RemoteConnection.SendQueryAsync(RCon.StaticHelpers.QueryType.GET_INFO);
return response.FirstOrDefault(r => r[0] == '\\')?.DictionaryFromKeyValue(); return response.FirstOrDefault(r => r[0] == '\\')?.DictionaryFromKeyValue();
} }