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
if (E.Type == GameEvent.EventType.Command &&
E.Extra != null &&
(canExecuteCommand ||
E.Origin?.Level == EFClient.Permission.Console))
if (E.Type == GameEvent.EventType.Command && E.Extra is Command command &&
(canExecuteCommand || E.Origin?.Level == 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
if (E.Extra == null)
{
var dict = await this.GetInfoAsync();
var dict = await this.GetInfoAsync(new TimeSpan(0, 0, 20));
if (dict == null)
{

View File

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

View File

@ -14,6 +14,7 @@ using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using static IW4MAdmin.Plugins.Stats.Cheat.Detection;
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)
{
// allow disabling of certain detection types
if (!ShouldUseDetection(attacker.CurrentServer.EndPoint, penalty.Type))
{
return;
}
var penaltyClient = Utilities.IW4MAdminClient(attacker.CurrentServer);
switch (penalty.ClientPenalty)
{

View File

@ -82,7 +82,7 @@ namespace IW4MAdmin.Plugins.Stats
break;
case GameEvent.EventType.ScriptKill:
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
if (IsWorldDamage(E.Origin))
@ -129,7 +129,7 @@ namespace IW4MAdmin.Plugins.Stats
break;
case GameEvent.EventType.ScriptDamage:
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
if (IsWorldDamage(E.Origin))
@ -515,5 +515,12 @@ namespace IW4MAdmin.Plugins.Stats
/// <param name="origin"></param>
/// <returns></returns>
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);
}
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];
for (int i = 0; i < 4; i++)
if (delay != null)
{
response = await server.RemoteConnection.SendQueryAsync(RCon.StaticHelpers.QueryType.GET_INFO);
if (response.Length == 2)
{
break;
}
await Task.Delay(RCon.StaticHelpers.FloodProtectionInterval);
await Task.Delay(delay.Value);
}
var response = await server.RemoteConnection.SendQueryAsync(RCon.StaticHelpers.QueryType.GET_INFO);
return response.FirstOrDefault(r => r[0] == '\\')?.DictionaryFromKeyValue();
}