fix T6 reading
add WaW support fix stats threading
This commit is contained in:
parent
e964013700
commit
6e5501b32d
@ -13,7 +13,7 @@ namespace IW4MAdmin.Application.EventParsers
|
|||||||
public virtual GameEvent GetEvent(Server server, string logLine)
|
public virtual GameEvent GetEvent(Server server, string logLine)
|
||||||
{
|
{
|
||||||
string[] lineSplit = logLine.Split(';');
|
string[] lineSplit = logLine.Split(';');
|
||||||
string cleanedEventLine = Regex.Replace(lineSplit[0], @"[0-9]+:[0-9]+\ ", "").Trim();
|
string cleanedEventLine = Regex.Replace(lineSplit[0], @"([0-9]+:[0-9]+ |^[0-9]+ )", "").Trim();
|
||||||
|
|
||||||
if (cleanedEventLine[0] == 'K')
|
if (cleanedEventLine[0] == 'K')
|
||||||
{
|
{
|
||||||
|
@ -9,9 +9,9 @@ using SharedLibraryCore.Objects;
|
|||||||
|
|
||||||
namespace IW4MAdmin.Application.EventParsers
|
namespace IW4MAdmin.Application.EventParsers
|
||||||
{
|
{
|
||||||
class T6MEventParser : IEventParser
|
class T6MEventParser : IW4EventParser
|
||||||
{
|
{
|
||||||
public GameEvent GetEvent(Server server, string logLine)
|
/*public GameEvent GetEvent(Server server, string logLine)
|
||||||
{
|
{
|
||||||
string cleanedEventLine = Regex.Replace(logLine, @"^ *[0-9]+:[0-9]+ *", "").Trim();
|
string cleanedEventLine = Regex.Replace(logLine, @"^ *[0-9]+:[0-9]+ *", "").Trim();
|
||||||
string[] lineSplit = cleanedEventLine.Split(';');
|
string[] lineSplit = cleanedEventLine.Split(';');
|
||||||
@ -104,8 +104,8 @@ namespace IW4MAdmin.Application.EventParsers
|
|||||||
},
|
},
|
||||||
Owner = server
|
Owner = server
|
||||||
};
|
};
|
||||||
}
|
}*/
|
||||||
|
|
||||||
public string GetGameDir() => $"t6r{Path.DirectorySeparatorChar}data";
|
public override string GetGameDir() => $"t6r{Path.DirectorySeparatorChar}data";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -139,7 +139,7 @@ namespace IW4MAdmin.Application
|
|||||||
sensitiveEvent.OnProcessed.Set();
|
sensitiveEvent.OnProcessed.Set();
|
||||||
}
|
}
|
||||||
|
|
||||||
await Task.Delay(5000);
|
await Task.Delay(1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
22
Application/RconParsers/IW3RConParser.cs
Normal file
22
Application/RconParsers/IW3RConParser.cs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
using Application.RconParsers;
|
||||||
|
using SharedLibraryCore.RCon;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Application.RconParsers
|
||||||
|
{
|
||||||
|
class IW3RConParser : IW4RConParser
|
||||||
|
{
|
||||||
|
private static CommandPrefix Prefixes = new CommandPrefix()
|
||||||
|
{
|
||||||
|
Tell = "tell {0} {1}",
|
||||||
|
Say = "say {0}",
|
||||||
|
Kick = "clientkick {0} \"{1}\"",
|
||||||
|
Ban = "clientkick {0} \"{1}\"",
|
||||||
|
TempBan = "tempbanclient {0} \"{1}\""
|
||||||
|
};
|
||||||
|
|
||||||
|
public override CommandPrefix GetCommandPrefixes() => Prefixes;
|
||||||
|
}
|
||||||
|
}
|
@ -23,7 +23,7 @@ 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-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}|loopback) +(-*[0-9]+) +([0-9]+) *$";
|
||||||
|
|
||||||
public async Task<string[]> ExecuteCommandAsync(Connection connection, string command)
|
public async Task<string[]> ExecuteCommandAsync(Connection connection, string command)
|
||||||
{
|
{
|
||||||
@ -72,7 +72,7 @@ namespace Application.RconParsers
|
|||||||
return (await connection.SendQueryAsync(StaticHelpers.QueryType.COMMAND, $"set {dvarName} {dvarValue}")).Length > 0;
|
return (await connection.SendQueryAsync(StaticHelpers.QueryType.COMMAND, $"set {dvarName} {dvarValue}")).Length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CommandPrefix GetCommandPrefixes() => Prefixes;
|
public virtual CommandPrefix GetCommandPrefixes() => Prefixes;
|
||||||
|
|
||||||
private List<Player> ClientsFromStatus(string[] Status)
|
private List<Player> ClientsFromStatus(string[] Status)
|
||||||
{
|
{
|
||||||
|
@ -723,7 +723,7 @@ namespace IW4MAdmin
|
|||||||
|
|
||||||
public async Task Initialize()
|
public async Task Initialize()
|
||||||
{
|
{
|
||||||
RconParser = ServerConfig.UseT6MParser ? (IRConParser)new T6MRConParser() : new IW4RConParser();
|
RconParser = ServerConfig.UseT6MParser ? (IRConParser)new T6MRConParser() : new IW3RConParser();
|
||||||
if (ServerConfig.UseIW5MParser)
|
if (ServerConfig.UseIW5MParser)
|
||||||
RconParser = new IW5MRConParser();
|
RconParser = new IW5MRConParser();
|
||||||
|
|
||||||
|
@ -6,17 +6,23 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
|
|
||||||
namespace IW4MAdmin.Plugins.Stats.Cheat
|
namespace IW4MAdmin.Plugins.Stats.Cheat
|
||||||
{
|
{
|
||||||
class Detection
|
class Detection
|
||||||
{
|
{
|
||||||
|
public enum DetectionType
|
||||||
|
{
|
||||||
|
Bone,
|
||||||
|
Chest,
|
||||||
|
Offset,
|
||||||
|
Strain
|
||||||
|
};
|
||||||
|
|
||||||
int Kills;
|
int Kills;
|
||||||
int HitCount;
|
int HitCount;
|
||||||
int AboveThresholdCount;
|
|
||||||
double AverageKillTime;
|
|
||||||
Dictionary<IW4Info.HitLocation, int> HitLocationCount;
|
Dictionary<IW4Info.HitLocation, int> HitLocationCount;
|
||||||
|
ChangeTracking Tracker;
|
||||||
double AngleDifferenceAverage;
|
double AngleDifferenceAverage;
|
||||||
EFClientStatistics ClientStats;
|
EFClientStatistics ClientStats;
|
||||||
DateTime LastHit;
|
DateTime LastHit;
|
||||||
@ -32,31 +38,7 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
|
|||||||
HitLocationCount.Add((IW4Info.HitLocation)loc, 0);
|
HitLocationCount.Add((IW4Info.HitLocation)loc, 0);
|
||||||
ClientStats = clientStats;
|
ClientStats = clientStats;
|
||||||
Strain = new Strain();
|
Strain = new Strain();
|
||||||
}
|
Tracker = new ChangeTracking();
|
||||||
|
|
||||||
public void ProcessScriptDamage(string damageLine)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ProcessDamage(string damageLine)
|
|
||||||
{
|
|
||||||
string regex = @"^(D);((?:bot[0-9]+)|(?:[A-Z]|[0-9])+);([0-9]+);(axis|allies);(.+);((?:[A-Z]|[0-9])+);([0-9]+);(axis|allies);(.+);((?:[0-9]+|[a-z]+|_)+);([0-9]+);((?:[A-Z]|_)+);((?:[a-z]|_)+)$";
|
|
||||||
|
|
||||||
var match = Regex.Match(damageLine, regex, RegexOptions.IgnoreCase);
|
|
||||||
|
|
||||||
if (match.Success)
|
|
||||||
{
|
|
||||||
var meansOfDeath = ParseEnum<IW4Info.MeansOfDeath>.Get(match.Groups[12].Value, typeof(IW4Info.MeansOfDeath));
|
|
||||||
var hitLocation = ParseEnum<IW4Info.HitLocation>.Get(match.Groups[13].Value, typeof(IW4Info.HitLocation));
|
|
||||||
|
|
||||||
if (meansOfDeath == IW4Info.MeansOfDeath.MOD_PISTOL_BULLET ||
|
|
||||||
meansOfDeath == IW4Info.MeansOfDeath.MOD_RIFLE_BULLET ||
|
|
||||||
meansOfDeath == IW4Info.MeansOfDeath.MOD_HEAD_SHOT)
|
|
||||||
{
|
|
||||||
ClientStats.HitLocations.First(hl => hl.Location == hitLocation).HitCount += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -111,8 +93,8 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
|
|||||||
return new DetectionPenaltyResult()
|
return new DetectionPenaltyResult()
|
||||||
{
|
{
|
||||||
ClientPenalty = Penalty.PenaltyType.Flag,
|
ClientPenalty = Penalty.PenaltyType.Flag,
|
||||||
RatioAmount = hitLoc.HitOffsetAverage,
|
Value = hitLoc.HitOffsetAverage,
|
||||||
KillCount = hitLoc.HitCount,
|
HitCount = hitLoc.HitCount,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,15 +106,16 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
|
|||||||
{
|
{
|
||||||
Log.WriteDebug("*** Reached Max Session Average for Angle Difference ***");
|
Log.WriteDebug("*** Reached Max Session Average for Angle Difference ***");
|
||||||
Log.WriteDebug($"Session Average = {sessAverage}");
|
Log.WriteDebug($"Session Average = {sessAverage}");
|
||||||
// Log.WriteDebug($"Bone = {hitLoc.Location}");
|
|
||||||
Log.WriteDebug($"HitCount = {HitCount}");
|
Log.WriteDebug($"HitCount = {HitCount}");
|
||||||
Log.WriteDebug($"ID = {kill.AttackerId}");
|
Log.WriteDebug($"ID = {kill.AttackerId}");
|
||||||
|
|
||||||
return new DetectionPenaltyResult()
|
return new DetectionPenaltyResult()
|
||||||
{
|
{
|
||||||
ClientPenalty = Penalty.PenaltyType.Flag,
|
ClientPenalty = Penalty.PenaltyType.Ban,
|
||||||
RatioAmount = sessAverage,
|
Value = sessAverage,
|
||||||
KillCount = HitCount,
|
HitCount = HitCount,
|
||||||
|
Type = DetectionType.Offset,
|
||||||
|
Location = hitLoc.Location
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,10 +123,8 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
|
|||||||
Log.WriteDebug($"PredictVsReal={realAgainstPredict}");
|
Log.WriteDebug($"PredictVsReal={realAgainstPredict}");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
var currentStrain = Strain.GetStrain(kill.ViewAngles, Math.Max(50, 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)
|
||||||
@ -151,14 +132,20 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
|
|||||||
ClientStats.MaxStrain = currentStrain;
|
ClientStats.MaxStrain = currentStrain;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentStrain > Thresholds.MaxStrain)
|
if (currentStrain > Thresholds.MaxStrainFlag)
|
||||||
{
|
{
|
||||||
Log.WriteDebug("*** Reached Max Strain ***");
|
Tracker.OnChange(Strain);
|
||||||
Log.WriteDebug($"Strain = {currentStrain}");
|
|
||||||
Log.WriteDebug($"Angles = {kill.ViewAngles} {kill.AnglesList[0]} {kill.AnglesList[1]}");
|
foreach (string change in Tracker.GetChanges())
|
||||||
Log.WriteDebug($"Time = {diff}");
|
{
|
||||||
Log.WriteDebug($"HitCount = {HitCount}");
|
Log.WriteDebug(change);
|
||||||
Log.WriteDebug($"ID = {kill.AttackerId}");
|
}
|
||||||
|
Log.WriteDebug(ClientStats.RoundScore.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Tracker.ClearChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Strain.TimesReachedMaxStrain >= 3)
|
if (Strain.TimesReachedMaxStrain >= 3)
|
||||||
@ -166,8 +153,9 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
|
|||||||
return new DetectionPenaltyResult()
|
return new DetectionPenaltyResult()
|
||||||
{
|
{
|
||||||
ClientPenalty = Penalty.PenaltyType.Flag,
|
ClientPenalty = Penalty.PenaltyType.Flag,
|
||||||
RatioAmount = ClientStats.MaxStrain,
|
Value = ClientStats.MaxStrain,
|
||||||
KillCount = HitCount,
|
HitCount = HitCount,
|
||||||
|
Type = DetectionType.Strain
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,46 +191,44 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
|
|||||||
// ban on headshot
|
// ban on headshot
|
||||||
if (currentHeadshotRatio > maxHeadshotLerpValueForFlag)
|
if (currentHeadshotRatio > maxHeadshotLerpValueForFlag)
|
||||||
{
|
{
|
||||||
AboveThresholdCount++;
|
|
||||||
Log.WriteDebug("**Maximum Headshot Ratio Reached For Ban**");
|
Log.WriteDebug("**Maximum Headshot Ratio Reached For Ban**");
|
||||||
Log.WriteDebug($"ClientId: {kill.AttackerId}");
|
Log.WriteDebug($"ClientId: {kill.AttackerId}");
|
||||||
Log.WriteDebug($"**Kills: {Kills}");
|
Log.WriteDebug($"**HitCount: {HitCount}");
|
||||||
Log.WriteDebug($"**Ratio {currentHeadshotRatio}");
|
Log.WriteDebug($"**Ratio {currentHeadshotRatio}");
|
||||||
Log.WriteDebug($"**MaxRatio {maxHeadshotLerpValueForFlag}");
|
Log.WriteDebug($"**MaxRatio {maxHeadshotLerpValueForFlag}");
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
foreach (var kvp in HitLocationCount)
|
foreach (var kvp in HitLocationCount)
|
||||||
sb.Append($"HitLocation: {kvp.Key} -> {kvp.Value}\r\n");
|
sb.Append($"HitLocation: {kvp.Key} -> {kvp.Value}\r\n");
|
||||||
Log.WriteDebug(sb.ToString());
|
Log.WriteDebug(sb.ToString());
|
||||||
Log.WriteDebug($"ThresholdReached: {AboveThresholdCount}");
|
|
||||||
|
|
||||||
return new DetectionPenaltyResult()
|
return new DetectionPenaltyResult()
|
||||||
{
|
{
|
||||||
ClientPenalty = Penalty.PenaltyType.Ban,
|
ClientPenalty = Penalty.PenaltyType.Ban,
|
||||||
RatioAmount = currentHeadshotRatio,
|
Value = currentHeadshotRatio,
|
||||||
Bone = IW4Info.HitLocation.head,
|
Location = IW4Info.HitLocation.head,
|
||||||
KillCount = Kills
|
HitCount = HitCount,
|
||||||
|
Type = DetectionType.Bone
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AboveThresholdCount++;
|
|
||||||
Log.WriteDebug("**Maximum Headshot Ratio Reached For Flag**");
|
Log.WriteDebug("**Maximum Headshot Ratio Reached For Flag**");
|
||||||
Log.WriteDebug($"ClientId: {kill.AttackerId}");
|
Log.WriteDebug($"ClientId: {kill.AttackerId}");
|
||||||
Log.WriteDebug($"**Kills: {Kills}");
|
Log.WriteDebug($"**HitCount: {HitCount}");
|
||||||
Log.WriteDebug($"**Ratio {currentHeadshotRatio}");
|
Log.WriteDebug($"**Ratio {currentHeadshotRatio}");
|
||||||
Log.WriteDebug($"**MaxRatio {maxHeadshotLerpValueForFlag}");
|
Log.WriteDebug($"**MaxRatio {maxHeadshotLerpValueForFlag}");
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
foreach (var kvp in HitLocationCount)
|
foreach (var kvp in HitLocationCount)
|
||||||
sb.Append($"HitLocation: {kvp.Key} -> {kvp.Value}\r\n");
|
sb.Append($"HitLocation: {kvp.Key} -> {kvp.Value}\r\n");
|
||||||
Log.WriteDebug(sb.ToString());
|
Log.WriteDebug(sb.ToString());
|
||||||
Log.WriteDebug($"ThresholdReached: {AboveThresholdCount}");
|
|
||||||
|
|
||||||
return new DetectionPenaltyResult()
|
return new DetectionPenaltyResult()
|
||||||
{
|
{
|
||||||
ClientPenalty = Penalty.PenaltyType.Flag,
|
ClientPenalty = Penalty.PenaltyType.Flag,
|
||||||
RatioAmount = currentHeadshotRatio,
|
Value = currentHeadshotRatio,
|
||||||
Bone = IW4Info.HitLocation.head,
|
Location = IW4Info.HitLocation.head,
|
||||||
KillCount = Kills
|
HitCount = HitCount,
|
||||||
|
Type = DetectionType.Bone
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -257,7 +243,7 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
|
|||||||
{
|
{
|
||||||
Log.WriteDebug("**Maximum Bone Ratio Reached For Ban**");
|
Log.WriteDebug("**Maximum Bone Ratio Reached For Ban**");
|
||||||
Log.WriteDebug($"ClientId: {kill.AttackerId}");
|
Log.WriteDebug($"ClientId: {kill.AttackerId}");
|
||||||
Log.WriteDebug($"**Kills: {Kills}");
|
Log.WriteDebug($"**HitCount: {HitCount}");
|
||||||
Log.WriteDebug($"**Ratio {currentMaxBoneRatio}");
|
Log.WriteDebug($"**Ratio {currentMaxBoneRatio}");
|
||||||
Log.WriteDebug($"**MaxRatio {maxBoneRatioLerpValueForBan}");
|
Log.WriteDebug($"**MaxRatio {maxBoneRatioLerpValueForBan}");
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
@ -268,16 +254,17 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
|
|||||||
return new DetectionPenaltyResult()
|
return new DetectionPenaltyResult()
|
||||||
{
|
{
|
||||||
ClientPenalty = Penalty.PenaltyType.Ban,
|
ClientPenalty = Penalty.PenaltyType.Ban,
|
||||||
RatioAmount = currentMaxBoneRatio,
|
Value = currentMaxBoneRatio,
|
||||||
Bone = bone,
|
Location = bone,
|
||||||
KillCount = Kills
|
HitCount = HitCount,
|
||||||
|
Type = DetectionType.Bone
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Log.WriteDebug("**Maximum Bone Ratio Reached For Flag**");
|
Log.WriteDebug("**Maximum Bone Ratio Reached For Flag**");
|
||||||
Log.WriteDebug($"ClientId: {kill.AttackerId}");
|
Log.WriteDebug($"ClientId: {kill.AttackerId}");
|
||||||
Log.WriteDebug($"**Kills: {Kills}");
|
Log.WriteDebug($"**HitCount: {HitCount}");
|
||||||
Log.WriteDebug($"**Ratio {currentMaxBoneRatio}");
|
Log.WriteDebug($"**Ratio {currentMaxBoneRatio}");
|
||||||
Log.WriteDebug($"**MaxRatio {maxBoneRatioLerpValueForFlag}");
|
Log.WriteDebug($"**MaxRatio {maxBoneRatioLerpValueForFlag}");
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
@ -288,9 +275,10 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
|
|||||||
return new DetectionPenaltyResult()
|
return new DetectionPenaltyResult()
|
||||||
{
|
{
|
||||||
ClientPenalty = Penalty.PenaltyType.Flag,
|
ClientPenalty = Penalty.PenaltyType.Flag,
|
||||||
RatioAmount = currentMaxBoneRatio,
|
Value = currentMaxBoneRatio,
|
||||||
Bone = bone,
|
Location = bone,
|
||||||
KillCount = Kills
|
HitCount = HitCount,
|
||||||
|
Type = DetectionType.Bone
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -298,12 +286,12 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
|
|||||||
}
|
}
|
||||||
|
|
||||||
#region CHEST_ABDOMEN_RATIO_SESSION
|
#region CHEST_ABDOMEN_RATIO_SESSION
|
||||||
int chestKills = HitLocationCount[IW4Info.HitLocation.torso_upper];
|
int chestHits = HitLocationCount[IW4Info.HitLocation.torso_upper];
|
||||||
|
|
||||||
if (chestKills >= Thresholds.MediumSampleMinKills)
|
if (chestHits >= Thresholds.MediumSampleMinKills)
|
||||||
{
|
{
|
||||||
double marginOfError = Thresholds.GetMarginOfError(chestKills);
|
double marginOfError = Thresholds.GetMarginOfError(chestHits);
|
||||||
double lerpAmount = Math.Min(1.0, (chestKills - Thresholds.MediumSampleMinKills) / (double)(Thresholds.HighSampleMinKills - Thresholds.LowSampleMinKills));
|
double lerpAmount = Math.Min(1.0, (chestHits - Thresholds.MediumSampleMinKills) / (double)(Thresholds.HighSampleMinKills - Thresholds.LowSampleMinKills));
|
||||||
// determine max acceptable ratio of chest to abdomen kills
|
// determine max acceptable ratio of chest to abdomen kills
|
||||||
double chestAbdomenRatioLerpValueForFlag = Thresholds.Lerp(Thresholds.ChestAbdomenRatioThresholdLowSample(3), Thresholds.ChestAbdomenRatioThresholdHighSample(3), lerpAmount) + marginOfError;
|
double chestAbdomenRatioLerpValueForFlag = Thresholds.Lerp(Thresholds.ChestAbdomenRatioThresholdLowSample(3), Thresholds.ChestAbdomenRatioThresholdHighSample(3), lerpAmount) + marginOfError;
|
||||||
double chestAbdomenLerpValueForBan = Thresholds.Lerp(Thresholds.ChestAbdomenRatioThresholdLowSample(4), Thresholds.ChestAbdomenRatioThresholdHighSample(4), lerpAmount) + marginOfError;
|
double chestAbdomenLerpValueForBan = Thresholds.Lerp(Thresholds.ChestAbdomenRatioThresholdLowSample(4), Thresholds.ChestAbdomenRatioThresholdHighSample(4), lerpAmount) + marginOfError;
|
||||||
@ -313,32 +301,32 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
|
|||||||
if (currentChestAbdomenRatio > chestAbdomenRatioLerpValueForFlag)
|
if (currentChestAbdomenRatio > chestAbdomenRatioLerpValueForFlag)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (currentChestAbdomenRatio > chestAbdomenLerpValueForBan && chestKills >= Thresholds.MediumSampleMinKills + 30)
|
if (currentChestAbdomenRatio > chestAbdomenLerpValueForBan && chestHits >= Thresholds.MediumSampleMinKills + 30)
|
||||||
{
|
{
|
||||||
Log.WriteDebug("**Maximum Chest/Abdomen Ratio Reached For Ban**");
|
Log.WriteDebug("**Maximum Chest/Abdomen Ratio Reached For Ban**");
|
||||||
Log.WriteDebug($"ClientId: {kill.AttackerId}");
|
Log.WriteDebug($"ClientId: {kill.AttackerId}");
|
||||||
Log.WriteDebug($"**Chest Kills: {chestKills}");
|
Log.WriteDebug($"**Chest Hits: {chestHits}");
|
||||||
Log.WriteDebug($"**Ratio {currentChestAbdomenRatio}");
|
Log.WriteDebug($"**Ratio {currentChestAbdomenRatio}");
|
||||||
Log.WriteDebug($"**MaxRatio {chestAbdomenLerpValueForBan}");
|
Log.WriteDebug($"**MaxRatio {chestAbdomenLerpValueForBan}");
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
foreach (var kvp in HitLocationCount)
|
foreach (var kvp in HitLocationCount)
|
||||||
sb.Append($"HitLocation: {kvp.Key} -> {kvp.Value}\r\n");
|
sb.Append($"HitLocation: {kvp.Key} -> {kvp.Value}\r\n");
|
||||||
Log.WriteDebug(sb.ToString());
|
Log.WriteDebug(sb.ToString());
|
||||||
// Log.WriteDebug($"ThresholdReached: {AboveThresholdCount}");
|
|
||||||
|
|
||||||
return new DetectionPenaltyResult()
|
return new DetectionPenaltyResult()
|
||||||
{
|
{
|
||||||
ClientPenalty = Penalty.PenaltyType.Ban,
|
ClientPenalty = Penalty.PenaltyType.Ban,
|
||||||
RatioAmount = currentChestAbdomenRatio,
|
Value = currentChestAbdomenRatio,
|
||||||
Bone = 0,
|
Location = IW4Info.HitLocation.torso_upper,
|
||||||
KillCount = chestKills
|
Type = DetectionType.Chest,
|
||||||
|
HitCount = chestHits
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Log.WriteDebug("**Maximum Chest/Abdomen Ratio Reached For Flag**");
|
Log.WriteDebug("**Maximum Chest/Abdomen Ratio Reached For Flag**");
|
||||||
Log.WriteDebug($"ClientId: {kill.AttackerId}");
|
Log.WriteDebug($"ClientId: {kill.AttackerId}");
|
||||||
Log.WriteDebug($"**Chest Kills: {chestKills}");
|
Log.WriteDebug($"**Chest Hits: {chestHits}");
|
||||||
Log.WriteDebug($"**Ratio {currentChestAbdomenRatio}");
|
Log.WriteDebug($"**Ratio {currentChestAbdomenRatio}");
|
||||||
Log.WriteDebug($"**MaxRatio {chestAbdomenRatioLerpValueForFlag}");
|
Log.WriteDebug($"**MaxRatio {chestAbdomenRatioLerpValueForFlag}");
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
@ -350,9 +338,10 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
|
|||||||
return new DetectionPenaltyResult()
|
return new DetectionPenaltyResult()
|
||||||
{
|
{
|
||||||
ClientPenalty = Penalty.PenaltyType.Flag,
|
ClientPenalty = Penalty.PenaltyType.Flag,
|
||||||
RatioAmount = currentChestAbdomenRatio,
|
Value = currentChestAbdomenRatio,
|
||||||
Bone = 0,
|
Location = IW4Info.HitLocation.torso_upper,
|
||||||
KillCount = chestKills
|
Type = DetectionType.Chest,
|
||||||
|
HitCount = chestHits
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -362,23 +351,22 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
|
|||||||
return new DetectionPenaltyResult()
|
return new DetectionPenaltyResult()
|
||||||
{
|
{
|
||||||
ClientPenalty = Penalty.PenaltyType.Any,
|
ClientPenalty = Penalty.PenaltyType.Any,
|
||||||
RatioAmount = 0
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public DetectionPenaltyResult ProcessTotalRatio(EFClientStatistics stats)
|
public DetectionPenaltyResult ProcessTotalRatio(EFClientStatistics stats)
|
||||||
{
|
{
|
||||||
int totalChestKills = stats.HitLocations.Single(c => c.Location == IW4Info.HitLocation.torso_upper).HitCount;
|
int totalChestHits = stats.HitLocations.Single(c => c.Location == IW4Info.HitLocation.torso_upper).HitCount;
|
||||||
|
|
||||||
if (totalChestKills >= 60)
|
if (totalChestHits >= 60)
|
||||||
{
|
{
|
||||||
double marginOfError = Thresholds.GetMarginOfError(totalChestKills);
|
double marginOfError = Thresholds.GetMarginOfError(totalChestHits);
|
||||||
double lerpAmount = Math.Min(1.0, (totalChestKills - 60) / 250.0);
|
double lerpAmount = Math.Min(1.0, (totalChestHits - 60) / 250.0);
|
||||||
// determine max acceptable ratio of chest to abdomen kills
|
// determine max acceptable ratio of chest to abdomen kills
|
||||||
double chestAbdomenRatioLerpValueForFlag = Thresholds.Lerp(Thresholds.ChestAbdomenRatioThresholdHighSample(3.0), Thresholds.ChestAbdomenRatioThresholdHighSample(2.0), lerpAmount) + marginOfError;
|
double chestAbdomenRatioLerpValueForFlag = Thresholds.Lerp(Thresholds.ChestAbdomenRatioThresholdHighSample(3.0), Thresholds.ChestAbdomenRatioThresholdHighSample(2.0), lerpAmount) + marginOfError;
|
||||||
double chestAbdomenLerpValueForBan = Thresholds.Lerp(Thresholds.ChestAbdomenRatioThresholdHighSample(4.0), Thresholds.ChestAbdomenRatioThresholdHighSample(3.0), lerpAmount) + marginOfError;
|
double chestAbdomenLerpValueForBan = Thresholds.Lerp(Thresholds.ChestAbdomenRatioThresholdHighSample(4.0), Thresholds.ChestAbdomenRatioThresholdHighSample(3.0), lerpAmount) + marginOfError;
|
||||||
|
|
||||||
double currentChestAbdomenRatio = totalChestKills /
|
double currentChestAbdomenRatio = totalChestHits /
|
||||||
stats.HitLocations.Single(hl => hl.Location == IW4Info.HitLocation.torso_lower).HitCount;
|
stats.HitLocations.Single(hl => hl.Location == IW4Info.HitLocation.torso_lower).HitCount;
|
||||||
|
|
||||||
if (currentChestAbdomenRatio > chestAbdomenRatioLerpValueForFlag)
|
if (currentChestAbdomenRatio > chestAbdomenRatioLerpValueForFlag)
|
||||||
@ -388,42 +376,42 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
|
|||||||
{
|
{
|
||||||
Log.WriteDebug("**Maximum Lifetime Chest/Abdomen Ratio Reached For Ban**");
|
Log.WriteDebug("**Maximum Lifetime Chest/Abdomen Ratio Reached For Ban**");
|
||||||
Log.WriteDebug($"ClientId: {stats.ClientId}");
|
Log.WriteDebug($"ClientId: {stats.ClientId}");
|
||||||
Log.WriteDebug($"**Total Chest Kills: {totalChestKills}");
|
Log.WriteDebug($"**Total Chest Hits: {totalChestHits}");
|
||||||
Log.WriteDebug($"**Ratio {currentChestAbdomenRatio}");
|
Log.WriteDebug($"**Ratio {currentChestAbdomenRatio}");
|
||||||
Log.WriteDebug($"**MaxRatio {chestAbdomenLerpValueForBan}");
|
Log.WriteDebug($"**MaxRatio {chestAbdomenLerpValueForBan}");
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
foreach (var location in stats.HitLocations)
|
foreach (var location in stats.HitLocations)
|
||||||
sb.Append($"HitLocation: {location.Location} -> {location.HitCount}\r\n");
|
sb.Append($"HitLocation: {location.Location} -> {location.HitCount}\r\n");
|
||||||
Log.WriteDebug(sb.ToString());
|
Log.WriteDebug(sb.ToString());
|
||||||
// Log.WriteDebug($"ThresholdReached: {AboveThresholdCount}");
|
|
||||||
|
|
||||||
return new DetectionPenaltyResult()
|
return new DetectionPenaltyResult()
|
||||||
{
|
{
|
||||||
ClientPenalty = Penalty.PenaltyType.Ban,
|
ClientPenalty = Penalty.PenaltyType.Ban,
|
||||||
RatioAmount = currentChestAbdomenRatio,
|
Value = currentChestAbdomenRatio,
|
||||||
Bone = IW4Info.HitLocation.torso_upper,
|
Location = IW4Info.HitLocation.torso_upper,
|
||||||
KillCount = totalChestKills
|
HitCount = totalChestHits,
|
||||||
|
Type = DetectionType.Chest
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Log.WriteDebug("**Maximum Lifetime Chest/Abdomen Ratio Reached For Flag**");
|
Log.WriteDebug("**Maximum Lifetime Chest/Abdomen Ratio Reached For Flag**");
|
||||||
Log.WriteDebug($"ClientId: {stats.ClientId}");
|
Log.WriteDebug($"ClientId: {stats.ClientId}");
|
||||||
Log.WriteDebug($"**Total Chest Kills: {totalChestKills}");
|
Log.WriteDebug($"**Total Chest Hits: {totalChestHits}");
|
||||||
Log.WriteDebug($"**Ratio {currentChestAbdomenRatio}");
|
Log.WriteDebug($"**Ratio {currentChestAbdomenRatio}");
|
||||||
Log.WriteDebug($"**MaxRatio {chestAbdomenRatioLerpValueForFlag}");
|
Log.WriteDebug($"**MaxRatio {chestAbdomenRatioLerpValueForFlag}");
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
foreach (var location in stats.HitLocations)
|
foreach (var location in stats.HitLocations)
|
||||||
sb.Append($"HitLocation: {location.Location} -> {location.HitCount}\r\n");
|
sb.Append($"HitLocation: {location.Location} -> {location.HitCount}\r\n");
|
||||||
Log.WriteDebug(sb.ToString());
|
Log.WriteDebug(sb.ToString());
|
||||||
// Log.WriteDebug($"ThresholdReached: {AboveThresholdCount}");
|
|
||||||
|
|
||||||
return new DetectionPenaltyResult()
|
return new DetectionPenaltyResult()
|
||||||
{
|
{
|
||||||
ClientPenalty = Penalty.PenaltyType.Flag,
|
ClientPenalty = Penalty.PenaltyType.Flag,
|
||||||
RatioAmount = currentChestAbdomenRatio,
|
Value = currentChestAbdomenRatio,
|
||||||
Bone = IW4Info.HitLocation.torso_upper,
|
Location = IW4Info.HitLocation.torso_upper,
|
||||||
KillCount = totalChestKills
|
HitCount = totalChestHits,
|
||||||
|
Type = DetectionType.Chest
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -431,7 +419,6 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
|
|||||||
|
|
||||||
return new DetectionPenaltyResult()
|
return new DetectionPenaltyResult()
|
||||||
{
|
{
|
||||||
Bone = IW4Info.HitLocation.none,
|
|
||||||
ClientPenalty = Penalty.PenaltyType.Any
|
ClientPenalty = Penalty.PenaltyType.Any
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -9,9 +9,10 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
|
|||||||
{
|
{
|
||||||
class DetectionPenaltyResult
|
class DetectionPenaltyResult
|
||||||
{
|
{
|
||||||
|
public Detection.DetectionType Type { get; set; }
|
||||||
public Penalty.PenaltyType ClientPenalty { get; set; }
|
public Penalty.PenaltyType ClientPenalty { get; set; }
|
||||||
public double RatioAmount { get; set; }
|
public double Value { get; set; }
|
||||||
public IW4Info.HitLocation Bone { get; set; }
|
public IW4Info.HitLocation Location { get; set; }
|
||||||
public int KillCount { get; set; }
|
public int HitCount { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,18 @@
|
|||||||
using SharedLibraryCore.Helpers;
|
using SharedLibraryCore.Helpers;
|
||||||
|
using SharedLibraryCore.Interfaces;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace IW4MAdmin.Plugins.Stats.Cheat
|
namespace IW4MAdmin.Plugins.Stats.Cheat
|
||||||
{
|
{
|
||||||
class Strain
|
class Strain : ITrackable
|
||||||
{
|
{
|
||||||
private static double StrainDecayBase = 0.15;
|
private static double StrainDecayBase = 0.15;
|
||||||
private double CurrentStrain;
|
private double CurrentStrain;
|
||||||
private Vector3 LastAngle;
|
private Vector3 LastAngle;
|
||||||
|
private double LastDeltaTime;
|
||||||
|
private double LastDistance;
|
||||||
|
|
||||||
public int TimesReachedMaxStrain { get; private set; }
|
public int TimesReachedMaxStrain { get; private set; }
|
||||||
|
|
||||||
@ -18,10 +21,13 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
|
|||||||
if (LastAngle == null)
|
if (LastAngle == null)
|
||||||
LastAngle = newAngle;
|
LastAngle = newAngle;
|
||||||
|
|
||||||
|
LastDeltaTime = deltaTime;
|
||||||
|
|
||||||
double decayFactor = GetDecay(deltaTime);
|
double decayFactor = GetDecay(deltaTime);
|
||||||
CurrentStrain *= decayFactor;
|
CurrentStrain *= decayFactor;
|
||||||
|
|
||||||
double[] distance = Helpers.Extensions.AngleStuff(newAngle, LastAngle);
|
double[] distance = Helpers.Extensions.AngleStuff(newAngle, LastAngle);
|
||||||
|
LastDistance = distance[0] + distance[1];
|
||||||
|
|
||||||
// this happens on first kill
|
// this happens on first kill
|
||||||
if ((distance[0] == 0 && distance[1] == 0) ||
|
if ((distance[0] == 0 && distance[1] == 0) ||
|
||||||
@ -34,13 +40,18 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
|
|||||||
double newStrain = Math.Pow(distance[0] + distance[1], 0.99) / deltaTime;
|
double newStrain = Math.Pow(distance[0] + distance[1], 0.99) / deltaTime;
|
||||||
CurrentStrain += newStrain;
|
CurrentStrain += newStrain;
|
||||||
|
|
||||||
if (CurrentStrain > Thresholds.MaxStrain)
|
if (CurrentStrain > Thresholds.MaxStrainFlag)
|
||||||
TimesReachedMaxStrain++;
|
TimesReachedMaxStrain++;
|
||||||
|
|
||||||
LastAngle = newAngle;
|
LastAngle = newAngle;
|
||||||
return CurrentStrain;
|
return CurrentStrain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string GetTrackableValue()
|
||||||
|
{
|
||||||
|
return $"Strain - {CurrentStrain}, Angle - {LastAngle}, Delta Time - {LastDeltaTime}, Distance - {LastDistance}";
|
||||||
|
}
|
||||||
|
|
||||||
private double GetDecay(double deltaTime) => Math.Pow(StrainDecayBase, deltaTime / 1000.0);
|
private double GetDecay(double deltaTime) => Math.Pow(StrainDecayBase, deltaTime / 1000.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -27,8 +27,9 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
|
|||||||
public const int HighSampleMinKills = 100;
|
public const int HighSampleMinKills = 100;
|
||||||
public const double KillTimeThreshold = 0.2;
|
public const double KillTimeThreshold = 0.2;
|
||||||
|
|
||||||
public const double MaxStrain = 0.4399;
|
public const double MaxStrainBan = 0.4399;
|
||||||
public const double MaxOffset = 4.789;
|
public const double MaxOffset = 4.789;
|
||||||
|
public const double MaxStrainFlag = 0.2;
|
||||||
|
|
||||||
public static double GetMarginOfError(int numKills) => 1.6455 / Math.Sqrt(numKills);
|
public static double GetMarginOfError(int numKills) => 1.6455 / Math.Sqrt(numKills);
|
||||||
|
|
||||||
|
@ -126,13 +126,10 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
|||||||
.ToList()
|
.ToList()
|
||||||
};
|
};
|
||||||
|
|
||||||
clientStats = statsSvc.ClientStatSvc.Insert(clientStats);
|
// insert if they've not been added
|
||||||
await statsSvc.ClientStatSvc.SaveChangesAsync();
|
var clientStatsSvc = statsSvc.ClientStatSvc;
|
||||||
}
|
clientStats = clientStatsSvc.Insert(clientStats);
|
||||||
|
await clientStatsSvc.SaveChangesAsync();
|
||||||
else
|
|
||||||
{
|
|
||||||
statsSvc.ClientStatSvc.Update(clientStats);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// migration for previous existing stats
|
// migration for previous existing stats
|
||||||
@ -161,9 +158,6 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
|||||||
if (!detectionStats.TryAdd(pl.ClientId, new Cheat.Detection(Log, clientStats)))
|
if (!detectionStats.TryAdd(pl.ClientId, new Cheat.Detection(Log, clientStats)))
|
||||||
Log.WriteDebug("Could not add client to detection");
|
Log.WriteDebug("Could not add client to detection");
|
||||||
|
|
||||||
/*
|
|
||||||
await statsSvc.ClientStatSvc.SaveChangesAsync();*/
|
|
||||||
|
|
||||||
return clientStats;
|
return clientStats;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,30 +187,39 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
|||||||
|
|
||||||
// get individual client's stats
|
// get individual client's stats
|
||||||
var clientStats = playerStats[pl.ClientId];
|
var clientStats = playerStats[pl.ClientId];
|
||||||
/*// sync their score
|
|
||||||
clientStats.SessionScore += pl.Score;*/
|
|
||||||
|
|
||||||
// remove the client from the stats dictionary as they're leaving
|
// remove the client from the stats dictionary as they're leaving
|
||||||
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);
|
||||||
|
// var clientStatsSvc = statsSvc.ClientStatSvc;
|
||||||
|
// clientStatsSvc.Update(clientStats);
|
||||||
|
// await clientStatsSvc.SaveChangesAsync();
|
||||||
|
|
||||||
statsSvc.ClientStatSvc.Update(clientStats);
|
|
||||||
await statsSvc.ClientStatSvc.SaveChangesAsync();
|
|
||||||
// increment the total play time
|
// increment the total play time
|
||||||
serverStats.TotalPlayTime += (int)(DateTime.UtcNow - pl.LastConnection).TotalSeconds;
|
serverStats.TotalPlayTime += (int)(DateTime.UtcNow - pl.LastConnection).TotalSeconds;
|
||||||
//await statsSvc.ServerStatsSvc.SaveChangesAsync();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddDamageEvent(string eventLine, int clientId, int serverId)
|
public void AddDamageEvent(string eventLine, int clientId, int serverId)
|
||||||
{
|
{
|
||||||
if (Plugin.Config.Configuration().EnableAntiCheat)
|
/* string regex = @"^(D);((?:bot[0-9]+)|(?:[A-Z]|[0-9])+);([0-9]+);(axis|allies);(.+);((?:[A-Z]|[0-9])+);([0-9]+);(axis|allies);(.+);((?:[0-9]+|[a-z]+|_)+);([0-9]+);((?:[A-Z]|_)+);((?:[a-z]|_)+)$";
|
||||||
{
|
|
||||||
var clientDetection = Servers[serverId].PlayerDetections[clientId];
|
var match = Regex.Match(damageLine, regex, RegexOptions.IgnoreCase);
|
||||||
clientDetection.ProcessScriptDamage(eventLine);
|
|
||||||
}
|
if (match.Success)
|
||||||
|
{
|
||||||
|
var meansOfDeath = ParseEnum<IW4Info.MeansOfDeath>.Get(match.Groups[12].Value, typeof(IW4Info.MeansOfDeath));
|
||||||
|
var hitLocation = ParseEnum<IW4Info.HitLocation>.Get(match.Groups[13].Value, typeof(IW4Info.HitLocation));
|
||||||
|
|
||||||
|
if (meansOfDeath == IW4Info.MeansOfDeath.MOD_PISTOL_BULLET ||
|
||||||
|
meansOfDeath == IW4Info.MeansOfDeath.MOD_RIFLE_BULLET ||
|
||||||
|
meansOfDeath == IW4Info.MeansOfDeath.MOD_HEAD_SHOT)
|
||||||
|
{
|
||||||
|
ClientStats.HitLocations.First(hl => hl.Location == hitLocation).HitCount += 1;
|
||||||
|
}
|
||||||
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -310,7 +313,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();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -330,19 +333,31 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
|||||||
switch (penalty.ClientPenalty)
|
switch (penalty.ClientPenalty)
|
||||||
{
|
{
|
||||||
case Penalty.PenaltyType.Ban:
|
case Penalty.PenaltyType.Ban:
|
||||||
await attacker.Ban(Utilities.CurrentLocalization.LocalizationIndex["PLUGIN_STATS_CHEAT_DETECTED"], new Player() { ClientId = 1 });
|
await attacker.Ban(Utilities.CurrentLocalization.LocalizationIndex["PLUGIN_STATS_CHEAT_DETECTED"], new Player()
|
||||||
|
{
|
||||||
|
ClientId = 1
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
case Penalty.PenaltyType.Flag:
|
case Penalty.PenaltyType.Flag:
|
||||||
if (attacker.Level != Player.Permission.User)
|
if (attacker.Level != Player.Permission.User)
|
||||||
break;
|
break;
|
||||||
var flagCmd = new CFlag();
|
var e = new GameEvent()
|
||||||
await flagCmd.ExecuteAsync(new GameEvent(GameEvent.EventType.Flag, $"{(int)penalty.Bone}-{Math.Round(penalty.RatioAmount, 2).ToString()}@{penalty.KillCount}", new Player()
|
|
||||||
{
|
{
|
||||||
ClientId = 1,
|
Data = penalty.Type == Cheat.Detection.DetectionType.Bone ?
|
||||||
Level = Player.Permission.Console,
|
$"{penalty.Type}-{(int)penalty.Location}-{Math.Round(penalty.Value, 2)}@{penalty.HitCount}" :
|
||||||
ClientNumber = -1,
|
$"{penalty.Type} -{Math.Round(penalty.Value, 2)}@{penalty.HitCount}",
|
||||||
CurrentServer = attacker.CurrentServer
|
Origin = new Player()
|
||||||
}, attacker, attacker.CurrentServer));
|
{
|
||||||
|
ClientId = 1,
|
||||||
|
Level = Player.Permission.Console,
|
||||||
|
ClientNumber = -1,
|
||||||
|
CurrentServer = attacker.CurrentServer
|
||||||
|
},
|
||||||
|
Target = attacker,
|
||||||
|
Owner = attacker.CurrentServer,
|
||||||
|
Type = GameEvent.EventType.Flag
|
||||||
|
};
|
||||||
|
await new CFlag().ExecuteAsync(e);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -433,10 +448,10 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
|||||||
}
|
}
|
||||||
|
|
||||||
// todo: do we want to save this immediately?
|
// todo: do we want to save this immediately?
|
||||||
var statsSvc = ContextThreads[serverId];
|
var statsSvc = ContextThreads[serverId].ClientStatSvc;
|
||||||
statsSvc.ClientStatSvc.Update(attackerStats);
|
statsSvc.Update(attackerStats);
|
||||||
statsSvc.ClientStatSvc.Update(victimStats);
|
statsSvc.Update(victimStats);
|
||||||
//await statsSvc.ClientStatSvc.SaveChangesAsync();
|
await statsSvc.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -463,7 +478,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
|||||||
victimStats.KillStreak = 0;
|
victimStats.KillStreak = 0;
|
||||||
|
|
||||||
// process the attacker's stats after the kills
|
// process the attacker's stats after the kills
|
||||||
attackerStats = UpdateStats(attackerStats);
|
//attackerStats = UpdateStats(attackerStats);
|
||||||
|
|
||||||
// update after calculation
|
// update after calculation
|
||||||
attackerStats.TimePlayed += (int)(DateTime.UtcNow - attackerStats.LastActive).TotalSeconds;
|
attackerStats.TimePlayed += (int)(DateTime.UtcNow - attackerStats.LastActive).TotalSeconds;
|
||||||
|
@ -10,7 +10,13 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
|||||||
{
|
{
|
||||||
public class ThreadSafeStatsService
|
public class ThreadSafeStatsService
|
||||||
{
|
{
|
||||||
public GenericRepository<EFClientStatistics> ClientStatSvc { get; private set; }
|
public GenericRepository<EFClientStatistics> ClientStatSvc
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return new GenericRepository<EFClientStatistics>();
|
||||||
|
}
|
||||||
|
}
|
||||||
public GenericRepository<EFServer> ServerSvc { get; private set; }
|
public GenericRepository<EFServer> ServerSvc { get; private set; }
|
||||||
public GenericRepository<EFClientKill> KillStatsSvc { get; private set; }
|
public GenericRepository<EFClientKill> KillStatsSvc { get; private set; }
|
||||||
public GenericRepository<EFServerStatistics> ServerStatsSvc { get; private set; }
|
public GenericRepository<EFServerStatistics> ServerStatsSvc { get; private set; }
|
||||||
@ -18,7 +24,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
|||||||
|
|
||||||
public ThreadSafeStatsService()
|
public ThreadSafeStatsService()
|
||||||
{
|
{
|
||||||
ClientStatSvc = new GenericRepository<EFClientStatistics>();
|
//ClientStatSvc = new GenericRepository<EFClientStatistics>();
|
||||||
ServerSvc = new GenericRepository<EFServer>();
|
ServerSvc = new GenericRepository<EFServer>();
|
||||||
KillStatsSvc = new GenericRepository<EFClientKill>();
|
KillStatsSvc = new GenericRepository<EFClientKill>();
|
||||||
ServerStatsSvc = new GenericRepository<EFServerStatistics>();
|
ServerStatsSvc = new GenericRepository<EFServerStatistics>();
|
||||||
|
41
SharedLibraryCore/Helpers/ChangeTracking.cs
Normal file
41
SharedLibraryCore/Helpers/ChangeTracking.cs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
using SharedLibraryCore.Interfaces;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace SharedLibraryCore.Helpers
|
||||||
|
{
|
||||||
|
public class ChangeTracking
|
||||||
|
{
|
||||||
|
List<string> Values;
|
||||||
|
|
||||||
|
public ChangeTracking()
|
||||||
|
{
|
||||||
|
Values = new List<string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnChange(ITrackable value)
|
||||||
|
{
|
||||||
|
Values.Add(value.GetTrackableValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearChanges()
|
||||||
|
{
|
||||||
|
Values.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string[] GetChanges()
|
||||||
|
{
|
||||||
|
List<string> values = new List<string>();
|
||||||
|
|
||||||
|
int number = 1;
|
||||||
|
foreach (string change in Values)
|
||||||
|
{
|
||||||
|
values.Add($"{number} {change}");
|
||||||
|
number++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return values.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
SharedLibraryCore/Interfaces/ITrackable.cs
Normal file
11
SharedLibraryCore/Interfaces/ITrackable.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace SharedLibraryCore.Interfaces
|
||||||
|
{
|
||||||
|
public interface ITrackable
|
||||||
|
{
|
||||||
|
string GetTrackableValue();
|
||||||
|
}
|
||||||
|
}
|
@ -242,7 +242,7 @@ namespace SharedLibraryCore
|
|||||||
return Game.IW4;
|
return Game.IW4;
|
||||||
if (gameName.Contains("CoD4"))
|
if (gameName.Contains("CoD4"))
|
||||||
return Game.IW3;
|
return Game.IW3;
|
||||||
if (gameName.Contains("WaW"))
|
if (gameName.Contains("COD_WaW"))
|
||||||
return Game.T4;
|
return Game.T4;
|
||||||
if (gameName.Contains("COD_T5_S"))
|
if (gameName.Contains("COD_T5_S"))
|
||||||
return Game.T5;
|
return Game.T5;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user