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:
parent
96e434213f
commit
f31ce6b001
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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()
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user