auth cookie expires after 30 days
only check hit offset when distance > 3 meters fix null reference on unauthorized user fixed stats not showing on profile if anticheat disabled server client history turns red server is unresponsive
This commit is contained in:
parent
c0865b82a0
commit
6d8d021b16
@ -60,7 +60,7 @@ namespace StatsPlugin.Cheat
|
||||
var calculatedVector = Vector3.Subtract(kill.KillOrigin, new Vector3((float)x, (float)y, (float)z));
|
||||
double angle = trueVector.AngleBetween(calculatedVector);
|
||||
|
||||
if (kill.AdsPercent > 0.5)
|
||||
if (kill.AdsPercent > 0.5 && kill.Distance > 3)
|
||||
{
|
||||
var hitLoc = ClientStats.HitLocations
|
||||
.First(hl => hl.Location == kill.HitLoc);
|
||||
@ -69,264 +69,264 @@ namespace StatsPlugin.Cheat
|
||||
hitLoc.HitOffsetAverage = (float)newAverage;
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region SESSION_RATIOS
|
||||
if (Kills >= Thresholds.LowSampleMinKills)
|
||||
{
|
||||
double marginOfError = Thresholds.GetMarginOfError(Kills);
|
||||
// determine what the max headshot percentage can be for current number of kills
|
||||
double lerpAmount = Math.Min(1.0, (Kills - Thresholds.LowSampleMinKills) / (double)(Thresholds.HighSampleMinKills - Thresholds.LowSampleMinKills));
|
||||
double maxHeadshotLerpValueForFlag = Thresholds.Lerp(Thresholds.HeadshotRatioThresholdLowSample(2.0), Thresholds.HeadshotRatioThresholdHighSample(2.0), lerpAmount) + marginOfError;
|
||||
double maxHeadshotLerpValueForBan = Thresholds.Lerp(Thresholds.HeadshotRatioThresholdLowSample(3.0), Thresholds.HeadshotRatioThresholdHighSample(3.0), lerpAmount) + marginOfError;
|
||||
// determine what the max bone percentage can be for current number of kills
|
||||
double maxBoneRatioLerpValueForFlag = Thresholds.Lerp(Thresholds.BoneRatioThresholdLowSample(2.25), Thresholds.BoneRatioThresholdHighSample(2.25), lerpAmount) + marginOfError;
|
||||
double maxBoneRatioLerpValueForBan = Thresholds.Lerp(Thresholds.BoneRatioThresholdLowSample(3.25), Thresholds.BoneRatioThresholdHighSample(3.25), lerpAmount) + marginOfError;
|
||||
#region SESSION_RATIOS
|
||||
if (Kills >= Thresholds.LowSampleMinKills)
|
||||
{
|
||||
double marginOfError = Thresholds.GetMarginOfError(Kills);
|
||||
// determine what the max headshot percentage can be for current number of kills
|
||||
double lerpAmount = Math.Min(1.0, (Kills - Thresholds.LowSampleMinKills) / (double)(Thresholds.HighSampleMinKills - Thresholds.LowSampleMinKills));
|
||||
double maxHeadshotLerpValueForFlag = Thresholds.Lerp(Thresholds.HeadshotRatioThresholdLowSample(2.0), Thresholds.HeadshotRatioThresholdHighSample(2.0), lerpAmount) + marginOfError;
|
||||
double maxHeadshotLerpValueForBan = Thresholds.Lerp(Thresholds.HeadshotRatioThresholdLowSample(3.0), Thresholds.HeadshotRatioThresholdHighSample(3.0), lerpAmount) + marginOfError;
|
||||
// determine what the max bone percentage can be for current number of kills
|
||||
double maxBoneRatioLerpValueForFlag = Thresholds.Lerp(Thresholds.BoneRatioThresholdLowSample(2.25), Thresholds.BoneRatioThresholdHighSample(2.25), lerpAmount) + marginOfError;
|
||||
double maxBoneRatioLerpValueForBan = Thresholds.Lerp(Thresholds.BoneRatioThresholdLowSample(3.25), Thresholds.BoneRatioThresholdHighSample(3.25), lerpAmount) + marginOfError;
|
||||
|
||||
// calculate headshot ratio
|
||||
double currentHeadshotRatio = ((HitLocationCount[IW4Info.HitLocation.head] + HitLocationCount[IW4Info.HitLocation.helmet]) / (double)Kills);
|
||||
// calculate maximum bone
|
||||
double currentMaxBoneRatio = (HitLocationCount.Values.Select(v => v / (double)Kills).Max());
|
||||
// calculate headshot ratio
|
||||
double currentHeadshotRatio = ((HitLocationCount[IW4Info.HitLocation.head] + HitLocationCount[IW4Info.HitLocation.helmet]) / (double)Kills);
|
||||
// calculate maximum bone
|
||||
double currentMaxBoneRatio = (HitLocationCount.Values.Select(v => v / (double)Kills).Max());
|
||||
|
||||
var bone = HitLocationCount.FirstOrDefault(b => b.Value == HitLocationCount.Values.Max()).Key;
|
||||
#region HEADSHOT_RATIO
|
||||
// flag on headshot
|
||||
if (currentHeadshotRatio > maxHeadshotLerpValueForFlag)
|
||||
{
|
||||
// ban on headshot
|
||||
if (currentHeadshotRatio > maxHeadshotLerpValueForFlag)
|
||||
{
|
||||
AboveThresholdCount++;
|
||||
Log.WriteDebug("**Maximum Headshot Ratio Reached For Ban**");
|
||||
Log.WriteDebug($"ClientId: {kill.AttackerId}");
|
||||
Log.WriteDebug($"**Kills: {Kills}");
|
||||
Log.WriteDebug($"**Ratio {currentHeadshotRatio}");
|
||||
Log.WriteDebug($"**MaxRatio {maxHeadshotLerpValueForFlag}");
|
||||
var sb = new StringBuilder();
|
||||
foreach (var kvp in HitLocationCount)
|
||||
sb.Append($"HitLocation: {kvp.Key} -> {kvp.Value}\r\n");
|
||||
Log.WriteDebug(sb.ToString());
|
||||
Log.WriteDebug($"ThresholdReached: {AboveThresholdCount}");
|
||||
var bone = HitLocationCount.FirstOrDefault(b => b.Value == HitLocationCount.Values.Max()).Key;
|
||||
#region HEADSHOT_RATIO
|
||||
// flag on headshot
|
||||
if (currentHeadshotRatio > maxHeadshotLerpValueForFlag)
|
||||
{
|
||||
// ban on headshot
|
||||
if (currentHeadshotRatio > maxHeadshotLerpValueForFlag)
|
||||
{
|
||||
AboveThresholdCount++;
|
||||
Log.WriteDebug("**Maximum Headshot Ratio Reached For Ban**");
|
||||
Log.WriteDebug($"ClientId: {kill.AttackerId}");
|
||||
Log.WriteDebug($"**Kills: {Kills}");
|
||||
Log.WriteDebug($"**Ratio {currentHeadshotRatio}");
|
||||
Log.WriteDebug($"**MaxRatio {maxHeadshotLerpValueForFlag}");
|
||||
var sb = new StringBuilder();
|
||||
foreach (var kvp in HitLocationCount)
|
||||
sb.Append($"HitLocation: {kvp.Key} -> {kvp.Value}\r\n");
|
||||
Log.WriteDebug(sb.ToString());
|
||||
Log.WriteDebug($"ThresholdReached: {AboveThresholdCount}");
|
||||
|
||||
return new DetectionPenaltyResult()
|
||||
{
|
||||
ClientPenalty = Penalty.PenaltyType.Ban,
|
||||
RatioAmount = currentHeadshotRatio,
|
||||
Bone = IW4Info.HitLocation.head,
|
||||
KillCount = Kills
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
AboveThresholdCount++;
|
||||
Log.WriteDebug("**Maximum Headshot Ratio Reached For Flag**");
|
||||
Log.WriteDebug($"ClientId: {kill.AttackerId}");
|
||||
Log.WriteDebug($"**Kills: {Kills}");
|
||||
Log.WriteDebug($"**Ratio {currentHeadshotRatio}");
|
||||
Log.WriteDebug($"**MaxRatio {maxHeadshotLerpValueForFlag}");
|
||||
var sb = new StringBuilder();
|
||||
foreach (var kvp in HitLocationCount)
|
||||
sb.Append($"HitLocation: {kvp.Key} -> {kvp.Value}\r\n");
|
||||
Log.WriteDebug(sb.ToString());
|
||||
Log.WriteDebug($"ThresholdReached: {AboveThresholdCount}");
|
||||
|
||||
return new DetectionPenaltyResult()
|
||||
{
|
||||
ClientPenalty = Penalty.PenaltyType.Flag,
|
||||
RatioAmount = currentHeadshotRatio,
|
||||
Bone = IW4Info.HitLocation.head,
|
||||
KillCount = Kills
|
||||
};
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region BONE_RATIO
|
||||
// flag on bone ratio
|
||||
else if (currentMaxBoneRatio > maxBoneRatioLerpValueForFlag)
|
||||
{
|
||||
// ban on bone ratio
|
||||
if (currentMaxBoneRatio > maxBoneRatioLerpValueForBan)
|
||||
{
|
||||
Log.WriteDebug("**Maximum Bone Ratio Reached For Ban**");
|
||||
Log.WriteDebug($"ClientId: {kill.AttackerId}");
|
||||
Log.WriteDebug($"**Kills: {Kills}");
|
||||
Log.WriteDebug($"**Ratio {currentMaxBoneRatio}");
|
||||
Log.WriteDebug($"**MaxRatio {maxBoneRatioLerpValueForBan}");
|
||||
var sb = new StringBuilder();
|
||||
foreach (var kvp in HitLocationCount)
|
||||
sb.Append($"HitLocation: {kvp.Key} -> {kvp.Value}\r\n");
|
||||
Log.WriteDebug(sb.ToString());
|
||||
|
||||
return new DetectionPenaltyResult()
|
||||
{
|
||||
ClientPenalty = Penalty.PenaltyType.Ban,
|
||||
RatioAmount = currentMaxBoneRatio,
|
||||
Bone = bone,
|
||||
KillCount = Kills
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.WriteDebug("**Maximum Bone Ratio Reached For Flag**");
|
||||
Log.WriteDebug($"ClientId: {kill.AttackerId}");
|
||||
Log.WriteDebug($"**Kills: {Kills}");
|
||||
Log.WriteDebug($"**Ratio {currentMaxBoneRatio}");
|
||||
Log.WriteDebug($"**MaxRatio {maxBoneRatioLerpValueForFlag}");
|
||||
var sb = new StringBuilder();
|
||||
foreach (var kvp in HitLocationCount)
|
||||
sb.Append($"HitLocation: {kvp.Key} -> {kvp.Value}\r\n");
|
||||
Log.WriteDebug(sb.ToString());
|
||||
|
||||
return new DetectionPenaltyResult()
|
||||
{
|
||||
ClientPenalty = Penalty.PenaltyType.Flag,
|
||||
RatioAmount = currentMaxBoneRatio,
|
||||
Bone = bone,
|
||||
KillCount = Kills
|
||||
};
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
#region CHEST_ABDOMEN_RATIO_SESSION
|
||||
int chestKills = HitLocationCount[IW4Info.HitLocation.torso_upper];
|
||||
|
||||
if (chestKills >= Thresholds.MediumSampleMinKills)
|
||||
{
|
||||
double marginOfError = Thresholds.GetMarginOfError(chestKills);
|
||||
double lerpAmount = Math.Min(1.0, (chestKills - Thresholds.LowSampleMinKills) / (double)(Thresholds.HighSampleMinKills - Thresholds.LowSampleMinKills));
|
||||
// determine max acceptable ratio of chest to abdomen kills
|
||||
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 currentChestAbdomenRatio = HitLocationCount[IW4Info.HitLocation.torso_upper] / (double)HitLocationCount[IW4Info.HitLocation.torso_lower];
|
||||
|
||||
if (currentChestAbdomenRatio > chestAbdomenRatioLerpValueForFlag)
|
||||
{
|
||||
|
||||
if (currentChestAbdomenRatio > chestAbdomenLerpValueForBan && chestKills >= Thresholds.MediumSampleMinKills + 30)
|
||||
{
|
||||
Log.WriteDebug("**Maximum Chest/Abdomen Ratio Reached For Ban**");
|
||||
Log.WriteDebug($"ClientId: {kill.AttackerId}");
|
||||
Log.WriteDebug($"**Chest Kills: {chestKills}");
|
||||
Log.WriteDebug($"**Ratio {currentChestAbdomenRatio}");
|
||||
Log.WriteDebug($"**MaxRatio {chestAbdomenLerpValueForBan}");
|
||||
var sb = new StringBuilder();
|
||||
foreach (var kvp in HitLocationCount)
|
||||
sb.Append($"HitLocation: {kvp.Key} -> {kvp.Value}\r\n");
|
||||
Log.WriteDebug(sb.ToString());
|
||||
// Log.WriteDebug($"ThresholdReached: {AboveThresholdCount}");
|
||||
|
||||
return new DetectionPenaltyResult()
|
||||
{
|
||||
ClientPenalty = Penalty.PenaltyType.Ban,
|
||||
RatioAmount = currentChestAbdomenRatio,
|
||||
Bone = 0,
|
||||
KillCount = chestKills
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.WriteDebug("**Maximum Chest/Abdomen Ratio Reached For Flag**");
|
||||
Log.WriteDebug($"ClientId: {kill.AttackerId}");
|
||||
Log.WriteDebug($"**Chest Kills: {chestKills}");
|
||||
Log.WriteDebug($"**Ratio {currentChestAbdomenRatio}");
|
||||
Log.WriteDebug($"**MaxRatio {chestAbdomenRatioLerpValueForFlag}");
|
||||
var sb = new StringBuilder();
|
||||
foreach (var kvp in HitLocationCount)
|
||||
sb.Append($"HitLocation: {kvp.Key} -> {kvp.Value}\r\n");
|
||||
Log.WriteDebug(sb.ToString());
|
||||
// Log.WriteDebug($"ThresholdReached: {AboveThresholdCount}");
|
||||
|
||||
return new DetectionPenaltyResult()
|
||||
{
|
||||
ClientPenalty = Penalty.PenaltyType.Flag,
|
||||
RatioAmount = currentChestAbdomenRatio,
|
||||
Bone = 0,
|
||||
KillCount = chestKills
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
return new DetectionPenaltyResult()
|
||||
{
|
||||
ClientPenalty = Penalty.PenaltyType.Ban,
|
||||
RatioAmount = currentHeadshotRatio,
|
||||
Bone = IW4Info.HitLocation.head,
|
||||
KillCount = Kills
|
||||
ClientPenalty = Penalty.PenaltyType.Any,
|
||||
RatioAmount = 0
|
||||
};
|
||||
}
|
||||
else
|
||||
|
||||
public DetectionPenaltyResult ProcessTotalRatio(EFClientStatistics stats)
|
||||
{
|
||||
AboveThresholdCount++;
|
||||
Log.WriteDebug("**Maximum Headshot Ratio Reached For Flag**");
|
||||
Log.WriteDebug($"ClientId: {kill.AttackerId}");
|
||||
Log.WriteDebug($"**Kills: {Kills}");
|
||||
Log.WriteDebug($"**Ratio {currentHeadshotRatio}");
|
||||
Log.WriteDebug($"**MaxRatio {maxHeadshotLerpValueForFlag}");
|
||||
var sb = new StringBuilder();
|
||||
foreach (var kvp in HitLocationCount)
|
||||
sb.Append($"HitLocation: {kvp.Key} -> {kvp.Value}\r\n");
|
||||
Log.WriteDebug(sb.ToString());
|
||||
Log.WriteDebug($"ThresholdReached: {AboveThresholdCount}");
|
||||
int totalChestKills = stats.HitLocations.Single(c => c.Location == IW4Info.HitLocation.left_arm_upper).HitCount;
|
||||
|
||||
return new DetectionPenaltyResult()
|
||||
if (totalChestKills >= 250)
|
||||
{
|
||||
ClientPenalty = Penalty.PenaltyType.Flag,
|
||||
RatioAmount = currentHeadshotRatio,
|
||||
Bone = IW4Info.HitLocation.head,
|
||||
KillCount = Kills
|
||||
};
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region BONE_RATIO
|
||||
// flag on bone ratio
|
||||
else if (currentMaxBoneRatio > maxBoneRatioLerpValueForFlag)
|
||||
{
|
||||
// ban on bone ratio
|
||||
if (currentMaxBoneRatio > maxBoneRatioLerpValueForBan)
|
||||
{
|
||||
Log.WriteDebug("**Maximum Bone Ratio Reached For Ban**");
|
||||
Log.WriteDebug($"ClientId: {kill.AttackerId}");
|
||||
Log.WriteDebug($"**Kills: {Kills}");
|
||||
Log.WriteDebug($"**Ratio {currentMaxBoneRatio}");
|
||||
Log.WriteDebug($"**MaxRatio {maxBoneRatioLerpValueForBan}");
|
||||
var sb = new StringBuilder();
|
||||
foreach (var kvp in HitLocationCount)
|
||||
sb.Append($"HitLocation: {kvp.Key} -> {kvp.Value}\r\n");
|
||||
Log.WriteDebug(sb.ToString());
|
||||
|
||||
return new DetectionPenaltyResult()
|
||||
{
|
||||
ClientPenalty = Penalty.PenaltyType.Ban,
|
||||
RatioAmount = currentMaxBoneRatio,
|
||||
Bone = bone,
|
||||
KillCount = Kills
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.WriteDebug("**Maximum Bone Ratio Reached For Flag**");
|
||||
Log.WriteDebug($"ClientId: {kill.AttackerId}");
|
||||
Log.WriteDebug($"**Kills: {Kills}");
|
||||
Log.WriteDebug($"**Ratio {currentMaxBoneRatio}");
|
||||
Log.WriteDebug($"**MaxRatio {maxBoneRatioLerpValueForFlag}");
|
||||
var sb = new StringBuilder();
|
||||
foreach (var kvp in HitLocationCount)
|
||||
sb.Append($"HitLocation: {kvp.Key} -> {kvp.Value}\r\n");
|
||||
Log.WriteDebug(sb.ToString());
|
||||
|
||||
return new DetectionPenaltyResult()
|
||||
{
|
||||
ClientPenalty = Penalty.PenaltyType.Flag,
|
||||
RatioAmount = currentMaxBoneRatio,
|
||||
Bone = bone,
|
||||
KillCount = Kills
|
||||
};
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
#region CHEST_ABDOMEN_RATIO_SESSION
|
||||
int chestKills = HitLocationCount[IW4Info.HitLocation.torso_upper];
|
||||
|
||||
if (chestKills >= Thresholds.MediumSampleMinKills)
|
||||
{
|
||||
double marginOfError = Thresholds.GetMarginOfError(chestKills);
|
||||
double lerpAmount = Math.Min(1.0, (chestKills - Thresholds.LowSampleMinKills) / (double)(Thresholds.HighSampleMinKills - Thresholds.LowSampleMinKills));
|
||||
// determine max acceptable ratio of chest to abdomen kills
|
||||
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 currentChestAbdomenRatio = HitLocationCount[IW4Info.HitLocation.torso_upper] / (double)HitLocationCount[IW4Info.HitLocation.torso_lower];
|
||||
|
||||
if (currentChestAbdomenRatio > chestAbdomenRatioLerpValueForFlag)
|
||||
{
|
||||
|
||||
if (currentChestAbdomenRatio > chestAbdomenLerpValueForBan && chestKills >= Thresholds.MediumSampleMinKills + 30)
|
||||
{
|
||||
Log.WriteDebug("**Maximum Chest/Abdomen Ratio Reached For Ban**");
|
||||
Log.WriteDebug($"ClientId: {kill.AttackerId}");
|
||||
Log.WriteDebug($"**Chest Kills: {chestKills}");
|
||||
Log.WriteDebug($"**Ratio {currentChestAbdomenRatio}");
|
||||
Log.WriteDebug($"**MaxRatio {chestAbdomenLerpValueForBan}");
|
||||
var sb = new StringBuilder();
|
||||
foreach (var kvp in HitLocationCount)
|
||||
sb.Append($"HitLocation: {kvp.Key} -> {kvp.Value}\r\n");
|
||||
Log.WriteDebug(sb.ToString());
|
||||
// Log.WriteDebug($"ThresholdReached: {AboveThresholdCount}");
|
||||
|
||||
return new DetectionPenaltyResult()
|
||||
{
|
||||
ClientPenalty = Penalty.PenaltyType.Ban,
|
||||
RatioAmount = currentChestAbdomenRatio,
|
||||
Bone = 0,
|
||||
KillCount = chestKills
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.WriteDebug("**Maximum Chest/Abdomen Ratio Reached For Flag**");
|
||||
Log.WriteDebug($"ClientId: {kill.AttackerId}");
|
||||
Log.WriteDebug($"**Chest Kills: {chestKills}");
|
||||
Log.WriteDebug($"**Ratio {currentChestAbdomenRatio}");
|
||||
Log.WriteDebug($"**MaxRatio {chestAbdomenRatioLerpValueForFlag}");
|
||||
var sb = new StringBuilder();
|
||||
foreach (var kvp in HitLocationCount)
|
||||
sb.Append($"HitLocation: {kvp.Key} -> {kvp.Value}\r\n");
|
||||
Log.WriteDebug(sb.ToString());
|
||||
// Log.WriteDebug($"ThresholdReached: {AboveThresholdCount}");
|
||||
|
||||
return new DetectionPenaltyResult()
|
||||
{
|
||||
ClientPenalty = Penalty.PenaltyType.Flag,
|
||||
RatioAmount = currentChestAbdomenRatio,
|
||||
Bone = 0,
|
||||
KillCount = chestKills
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
return new DetectionPenaltyResult()
|
||||
{
|
||||
ClientPenalty = Penalty.PenaltyType.Any,
|
||||
RatioAmount = 0
|
||||
};
|
||||
}
|
||||
|
||||
public DetectionPenaltyResult ProcessTotalRatio(EFClientStatistics stats)
|
||||
{
|
||||
int totalChestKills = stats.HitLocations.Single(c => c.Location == IW4Info.HitLocation.left_arm_upper).HitCount;
|
||||
|
||||
if (totalChestKills >= 250)
|
||||
{
|
||||
double marginOfError = Thresholds.GetMarginOfError(totalChestKills);
|
||||
double lerpAmount = Math.Min(1.0, (totalChestKills - Thresholds.LowSampleMinKills) / (double)(Thresholds.HighSampleMinKills - Thresholds.LowSampleMinKills));
|
||||
// determine max acceptable ratio of chest to abdomen kills
|
||||
double chestAbdomenRatioLerpValueForFlag = Thresholds.Lerp(Thresholds.ChestAbdomenRatioThresholdLowSample(2.25), Thresholds.ChestAbdomenRatioThresholdHighSample(2.25), lerpAmount) + marginOfError;
|
||||
double chestAbdomenLerpValueForBan = Thresholds.Lerp(Thresholds.ChestAbdomenRatioThresholdLowSample(3.0), Thresholds.ChestAbdomenRatioThresholdHighSample(3.0), lerpAmount) + marginOfError;
|
||||
double marginOfError = Thresholds.GetMarginOfError(totalChestKills);
|
||||
double lerpAmount = Math.Min(1.0, (totalChestKills - Thresholds.LowSampleMinKills) / (double)(Thresholds.HighSampleMinKills - Thresholds.LowSampleMinKills));
|
||||
// determine max acceptable ratio of chest to abdomen kills
|
||||
double chestAbdomenRatioLerpValueForFlag = Thresholds.Lerp(Thresholds.ChestAbdomenRatioThresholdLowSample(2.25), Thresholds.ChestAbdomenRatioThresholdHighSample(2.25), lerpAmount) + marginOfError;
|
||||
double chestAbdomenLerpValueForBan = Thresholds.Lerp(Thresholds.ChestAbdomenRatioThresholdLowSample(3.0), Thresholds.ChestAbdomenRatioThresholdHighSample(3.0), lerpAmount) + marginOfError;
|
||||
|
||||
double currentChestAbdomenRatio = stats.HitLocations.Single(hl => hl.Location == IW4Info.HitLocation.torso_upper).HitCount /
|
||||
stats.HitLocations.Single(hl => hl.Location == IW4Info.HitLocation.torso_lower).HitCount;
|
||||
|
||||
if (currentChestAbdomenRatio > chestAbdomenRatioLerpValueForFlag)
|
||||
{
|
||||
if (currentChestAbdomenRatio > chestAbdomenRatioLerpValueForFlag)
|
||||
{
|
||||
|
||||
if (currentChestAbdomenRatio > chestAbdomenLerpValueForBan)
|
||||
{
|
||||
Log.WriteDebug("**Maximum Lifetime Chest/Abdomen Ratio Reached For Ban**");
|
||||
Log.WriteDebug($"ClientId: {stats.ClientId}");
|
||||
Log.WriteDebug($"**Total Chest Kills: {totalChestKills}");
|
||||
Log.WriteDebug($"**Ratio {currentChestAbdomenRatio}");
|
||||
Log.WriteDebug($"**MaxRatio {chestAbdomenLerpValueForBan}");
|
||||
var sb = new StringBuilder();
|
||||
foreach (var location in stats.HitLocations)
|
||||
sb.Append($"HitLocation: {location.Location} -> {location.HitCount}\r\n");
|
||||
Log.WriteDebug(sb.ToString());
|
||||
// Log.WriteDebug($"ThresholdReached: {AboveThresholdCount}");
|
||||
if (currentChestAbdomenRatio > chestAbdomenLerpValueForBan)
|
||||
{
|
||||
Log.WriteDebug("**Maximum Lifetime Chest/Abdomen Ratio Reached For Ban**");
|
||||
Log.WriteDebug($"ClientId: {stats.ClientId}");
|
||||
Log.WriteDebug($"**Total Chest Kills: {totalChestKills}");
|
||||
Log.WriteDebug($"**Ratio {currentChestAbdomenRatio}");
|
||||
Log.WriteDebug($"**MaxRatio {chestAbdomenLerpValueForBan}");
|
||||
var sb = new StringBuilder();
|
||||
foreach (var location in stats.HitLocations)
|
||||
sb.Append($"HitLocation: {location.Location} -> {location.HitCount}\r\n");
|
||||
Log.WriteDebug(sb.ToString());
|
||||
// Log.WriteDebug($"ThresholdReached: {AboveThresholdCount}");
|
||||
|
||||
return new DetectionPenaltyResult()
|
||||
{
|
||||
ClientPenalty = Penalty.PenaltyType.Ban,
|
||||
RatioAmount = currentChestAbdomenRatio,
|
||||
Bone = IW4Info.HitLocation.torso_upper,
|
||||
KillCount = totalChestKills
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.WriteDebug("**Maximum Lifetime Chest/Abdomen Ratio Reached For Flag**");
|
||||
Log.WriteDebug($"ClientId: {stats.ClientId}");
|
||||
Log.WriteDebug($"**Total Chest Kills: {totalChestKills}");
|
||||
Log.WriteDebug($"**Ratio {currentChestAbdomenRatio}");
|
||||
Log.WriteDebug($"**MaxRatio {chestAbdomenRatioLerpValueForFlag}");
|
||||
var sb = new StringBuilder();
|
||||
foreach (var location in stats.HitLocations)
|
||||
sb.Append($"HitLocation: {location.Location} -> {location.HitCount}\r\n");
|
||||
Log.WriteDebug(sb.ToString());
|
||||
// Log.WriteDebug($"ThresholdReached: {AboveThresholdCount}");
|
||||
|
||||
return new DetectionPenaltyResult()
|
||||
{
|
||||
ClientPenalty = Penalty.PenaltyType.Flag,
|
||||
RatioAmount = currentChestAbdomenRatio,
|
||||
Bone = IW4Info.HitLocation.torso_upper,
|
||||
KillCount = totalChestKills
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new DetectionPenaltyResult()
|
||||
{
|
||||
ClientPenalty = Penalty.PenaltyType.Ban,
|
||||
RatioAmount = currentChestAbdomenRatio,
|
||||
Bone = IW4Info.HitLocation.torso_upper,
|
||||
KillCount = totalChestKills
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.WriteDebug("**Maximum Lifetime Chest/Abdomen Ratio Reached For Flag**");
|
||||
Log.WriteDebug($"ClientId: {stats.ClientId}");
|
||||
Log.WriteDebug($"**Total Chest Kills: {totalChestKills}");
|
||||
Log.WriteDebug($"**Ratio {currentChestAbdomenRatio}");
|
||||
Log.WriteDebug($"**MaxRatio {chestAbdomenRatioLerpValueForFlag}");
|
||||
var sb = new StringBuilder();
|
||||
foreach (var location in stats.HitLocations)
|
||||
sb.Append($"HitLocation: {location.Location} -> {location.HitCount}\r\n");
|
||||
Log.WriteDebug(sb.ToString());
|
||||
// Log.WriteDebug($"ThresholdReached: {AboveThresholdCount}");
|
||||
|
||||
return new DetectionPenaltyResult()
|
||||
{
|
||||
ClientPenalty = Penalty.PenaltyType.Flag,
|
||||
RatioAmount = currentChestAbdomenRatio,
|
||||
Bone = IW4Info.HitLocation.torso_upper,
|
||||
KillCount = totalChestKills
|
||||
Bone = IW4Info.HitLocation.none,
|
||||
ClientPenalty = Penalty.PenaltyType.Any
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new DetectionPenaltyResult()
|
||||
{
|
||||
Bone = IW4Info.HitLocation.none,
|
||||
ClientPenalty = Penalty.PenaltyType.Any
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -380,7 +380,7 @@ namespace StatsPlugin.Helpers
|
||||
double timeSinceLastActive = (DateTime.UtcNow - clientStats.LastActive).TotalSeconds / 60.0;
|
||||
|
||||
// prevent NaN or inactive time lowering SPM
|
||||
if (timeSinceLastCalc == 0 || timeSinceLastActive > 3)
|
||||
if (timeSinceLastCalc == 0 || timeSinceLastActive > 3 || clientStats.SPM < 1)
|
||||
return clientStats;
|
||||
|
||||
// calculate the players Score Per Minute for the current session
|
||||
@ -403,6 +403,9 @@ namespace StatsPlugin.Helpers
|
||||
|
||||
// calculate the new weight against average times the weight against play time
|
||||
clientStats.SPM = (killSPM * SPMAgainstPlayWeight) + (clientStats.SPM * (1 - SPMAgainstPlayWeight));
|
||||
// fixme: how does this happen?
|
||||
if (clientStats.SPM == double.NaN)
|
||||
clientStats.SPM = 0;
|
||||
clientStats.SPM = Math.Round(clientStats.SPM, 3);
|
||||
clientStats.Skill = Math.Round((clientStats.SPM * KDRWeight), 3);
|
||||
|
||||
|
@ -105,6 +105,41 @@ namespace StatsPlugin
|
||||
double skill = Math.Round(clientStats.Sum(c => c.Skill) / clientStats.Count, 2);
|
||||
double spm = Math.Round(clientStats.Sum(c => c.SPM), 1);
|
||||
|
||||
return new List<ProfileMeta>()
|
||||
{
|
||||
new ProfileMeta()
|
||||
{
|
||||
Key = "Kills",
|
||||
Value = kills
|
||||
},
|
||||
new ProfileMeta()
|
||||
{
|
||||
Key = "Deaths",
|
||||
Value = deaths
|
||||
},
|
||||
new ProfileMeta()
|
||||
{
|
||||
Key = "KDR",
|
||||
Value = kdr
|
||||
},
|
||||
new ProfileMeta()
|
||||
{
|
||||
Key = "Skill",
|
||||
Value = skill
|
||||
},
|
||||
new ProfileMeta()
|
||||
{
|
||||
Key = "Score Per Minute",
|
||||
Value = spm
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
async Task<List<ProfileMeta>> getAnticheatInfo(int clientId)
|
||||
{
|
||||
var statsSvc = new GenericRepository<EFClientStatistics>();
|
||||
var clientStats = await statsSvc.FindAsync(c => c.ClientId == clientId);
|
||||
|
||||
double headRatio = 0;
|
||||
double chestRatio = 0;
|
||||
double abdomenRatio = 0;
|
||||
@ -134,61 +169,36 @@ namespace StatsPlugin
|
||||
|
||||
return new List<ProfileMeta>()
|
||||
{
|
||||
new ProfileMeta()
|
||||
{
|
||||
Key = "Kills",
|
||||
Value = kills
|
||||
},
|
||||
new ProfileMeta()
|
||||
{
|
||||
Key = "Deaths",
|
||||
Value = deaths
|
||||
},
|
||||
new ProfileMeta()
|
||||
{
|
||||
Key = "KDR",
|
||||
Value = kdr
|
||||
},
|
||||
new ProfileMeta()
|
||||
{
|
||||
Key = "Skill",
|
||||
Value = skill
|
||||
},
|
||||
new ProfileMeta()
|
||||
{
|
||||
Key = "Score Per Minute",
|
||||
Value = spm
|
||||
},
|
||||
new ProfileMeta()
|
||||
{
|
||||
Key = "Chest Ratio",
|
||||
Value = chestRatio,
|
||||
Sensitive = true
|
||||
},
|
||||
new ProfileMeta()
|
||||
{
|
||||
Key = "Abdomen Ratio",
|
||||
Value = abdomenRatio,
|
||||
Sensitive = true
|
||||
},
|
||||
new ProfileMeta()
|
||||
{
|
||||
Key = "Chest To Abdomen Ratio",
|
||||
Value = chestAbdomenRatio,
|
||||
Sensitive = true
|
||||
},
|
||||
new ProfileMeta()
|
||||
{
|
||||
Key = "Headshot Ratio",
|
||||
Value = headRatio,
|
||||
Sensitive = true
|
||||
},
|
||||
new ProfileMeta()
|
||||
{
|
||||
Key = "Hit Offset Average",
|
||||
Value = $"{Math.Round(((float)hitOffsetAverage).ToDegrees(), 4)}°",
|
||||
Sensitive = true
|
||||
}
|
||||
new ProfileMeta()
|
||||
{
|
||||
Key = "Chest Ratio",
|
||||
Value = chestRatio,
|
||||
Sensitive = true
|
||||
},
|
||||
new ProfileMeta()
|
||||
{
|
||||
Key = "Abdomen Ratio",
|
||||
Value = abdomenRatio,
|
||||
Sensitive = true
|
||||
},
|
||||
new ProfileMeta()
|
||||
{
|
||||
Key = "Chest To Abdomen Ratio",
|
||||
Value = chestAbdomenRatio,
|
||||
Sensitive = true
|
||||
},
|
||||
new ProfileMeta()
|
||||
{
|
||||
Key = "Headshot Ratio",
|
||||
Value = headRatio,
|
||||
Sensitive = true
|
||||
},
|
||||
new ProfileMeta()
|
||||
{
|
||||
Key = "Hit Offset Average",
|
||||
Value = $"{Math.Round(((float)hitOffsetAverage).ToDegrees(), 4)}°",
|
||||
Sensitive = true
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -211,10 +221,13 @@ namespace StatsPlugin
|
||||
return messageMeta;
|
||||
}
|
||||
|
||||
MetaService.AddMeta(getStats);
|
||||
|
||||
if (Config.Configuration().EnableAntiCheat)
|
||||
{
|
||||
MetaService.AddMeta(getStats);
|
||||
MetaService.AddMeta(getAnticheatInfo);
|
||||
}
|
||||
|
||||
MetaService.AddMeta(getMessages);
|
||||
|
||||
// todo: is this fast? make async?
|
||||
@ -240,10 +253,7 @@ namespace StatsPlugin
|
||||
Manager = new StatManager(manager);
|
||||
}
|
||||
|
||||
public async Task OnTickAsync(Server S)
|
||||
{
|
||||
|
||||
}
|
||||
public Task OnTickAsync(Server S) => Utilities.CompletedTask;
|
||||
|
||||
public async Task OnUnloadAsync()
|
||||
{
|
||||
|
@ -75,13 +75,9 @@ namespace Welcome_Plugin
|
||||
}
|
||||
}
|
||||
|
||||
public async Task OnUnloadAsync()
|
||||
{
|
||||
}
|
||||
public Task OnUnloadAsync() => Utilities.CompletedTask;
|
||||
|
||||
public async Task OnTickAsync(Server S)
|
||||
{
|
||||
}
|
||||
public Task OnTickAsync(Server S) => Utilities.CompletedTask;
|
||||
|
||||
public async Task OnEventAsync(Event E, Server S)
|
||||
{
|
||||
|
@ -457,6 +457,16 @@ namespace SharedLibrary.Commands
|
||||
await E.Owner.Manager.GetClientService().Update(E.Target);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
E.Owner.Manager.GetPrivilegedClients().Add(E.Target.ClientId, E.Target);
|
||||
}
|
||||
|
||||
catch (Exception)
|
||||
{
|
||||
E.Owner.Manager.GetPrivilegedClients()[E.Target.ClientId] = E.Target;
|
||||
}
|
||||
|
||||
await E.Origin.Tell($"{E.Target.Name} was successfully promoted");
|
||||
}
|
||||
|
||||
@ -989,12 +999,22 @@ namespace SharedLibrary.Commands
|
||||
|
||||
public override async Task ExecuteAsync(Event E)
|
||||
{
|
||||
if (E.Data.Length < 5)
|
||||
{
|
||||
await E.Origin.Tell("Your password must be atleast 5 characters long");
|
||||
return;
|
||||
}
|
||||
|
||||
string[] hashedPassword = Helpers.Hashing.Hash(E.Data);
|
||||
|
||||
E.Origin.Password = hashedPassword[0];
|
||||
E.Origin.PasswordSalt = hashedPassword[1];
|
||||
|
||||
// update the password for the client in privileged
|
||||
E.Owner.Manager.GetPrivilegedClients()[E.Origin.ClientId] = E.Origin;
|
||||
|
||||
await E.Owner.Manager.GetClientService().Update(E.Origin);
|
||||
await E.Origin.Tell("Your password has been set successfully");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,18 @@ namespace SharedLibrary.Database
|
||||
#if !DEBUG
|
||||
foreach (string dllPath in System.IO.Directory.GetFiles($"{Utilities.OperatingDirectory}Plugins"))
|
||||
#else
|
||||
foreach (string dllPath in System.IO.Directory.GetFiles(/*C:\Projects\IW4M - Admin\WebfrontCore */ $@"{Environment.CurrentDirectory}\bin\x86\Debug\Plugins").Where(f => f.Contains(".dll")))
|
||||
IEnumerable<string> directoryFiles;
|
||||
try
|
||||
{
|
||||
directoryFiles = Directory.GetFiles($@"{Environment.CurrentDirectory}\bin\x86\Debug\Plugins").Where(f => f.Contains(".dll"));
|
||||
}
|
||||
|
||||
catch(Exception)
|
||||
{
|
||||
directoryFiles = Directory.GetFiles($@"{Environment.CurrentDirectory}\Plugins").Where(f => f.Contains(".dll"));
|
||||
}
|
||||
|
||||
foreach (string dllPath in directoryFiles)
|
||||
#endif
|
||||
{
|
||||
Assembly library;
|
||||
|
@ -2,9 +2,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SharedLibrary.Database.Models
|
||||
{
|
||||
|
@ -18,5 +18,6 @@ namespace SharedLibrary.Dtos
|
||||
public List<PlayerInfo> Players { get; set; }
|
||||
public Helpers.PlayerHistory[] PlayerHistory { get; set; }
|
||||
public int ID { get; set; }
|
||||
public bool Online { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -22,5 +22,6 @@ namespace SharedLibrary.Interfaces
|
||||
ClientService GetClientService();
|
||||
AliasService GetAliasService();
|
||||
PenaltyService GetPenaltyService();
|
||||
IDictionary<int, Player> GetPrivilegedClients();
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,6 @@ namespace SharedLibrary.RCon
|
||||
}
|
||||
|
||||
public static char SeperatorChar = (char)int.Parse("0a", System.Globalization.NumberStyles.AllowHexSpecifier);
|
||||
public static readonly TimeSpan SocketTimeout = new TimeSpan(0, 0, 1);
|
||||
public static readonly TimeSpan SocketTimeout = new TimeSpan(0, 0, 10);
|
||||
}
|
||||
}
|
||||
|
@ -142,6 +142,7 @@ namespace SharedLibrary
|
||||
await this.ExecuteCommandAsync($"{sayCommand} {(CustomSayEnabled ? CustomSayName : "")} {Message}");
|
||||
#else
|
||||
Logger.WriteVerbose(Message.StripColors());
|
||||
await Utilities.CompletedTask;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -159,6 +160,7 @@ namespace SharedLibrary
|
||||
await this.ExecuteCommandAsync($"{tellCommand} {Target.ClientNumber} {(CustomSayEnabled ? CustomSayName : "")} {Message}^7");
|
||||
#else
|
||||
Logger.WriteVerbose($"{Target.ClientNumber}->{Message.StripColors()}");
|
||||
await Utilities.CompletedTask;
|
||||
#endif
|
||||
|
||||
if (Target.Level == Player.Permission.Console)
|
||||
|
@ -16,8 +16,8 @@ namespace SharedLibrary.Services
|
||||
{
|
||||
public async Task<EFAlias> Create(EFAlias entity)
|
||||
{
|
||||
throw new Exception();
|
||||
using (var context = new DatabaseContext())
|
||||
throw await Task.FromResult(new Exception());
|
||||
/*using (var context = new DatabaseContext())
|
||||
{
|
||||
var alias = new EFAlias()
|
||||
{
|
||||
@ -32,7 +32,7 @@ namespace SharedLibrary.Services
|
||||
context.Aliases.Add(entity);
|
||||
await context.SaveChangesAsync();
|
||||
return entity;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
public Task<EFAlias> CreateProxy()
|
||||
@ -80,14 +80,14 @@ namespace SharedLibrary.Services
|
||||
|
||||
public async Task<EFAlias> Update(EFAlias entity)
|
||||
{
|
||||
throw new Exception();
|
||||
using (var context = new DatabaseContext())
|
||||
throw await Task.FromResult(new Exception());
|
||||
/*using (var context = new DatabaseContext())
|
||||
{
|
||||
entity = context.Aliases.Attach(entity);
|
||||
context.Entry(entity).State = EntityState.Modified;
|
||||
await context.SaveChangesAsync();
|
||||
return entity;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
public async Task<EFAliasLink> CreateLink(EFAliasLink link)
|
||||
|
@ -59,6 +59,8 @@ namespace SharedLibrary.Services
|
||||
|
||||
public async Task<IList<EFPenalty>> Find(Func<EFPenalty, bool> expression)
|
||||
{
|
||||
throw await Task.FromResult(new Exception());
|
||||
/*
|
||||
return await Task.FromResult(new List<EFPenalty>());
|
||||
// fixme: this is so slow!
|
||||
return await Task.Run(() =>
|
||||
@ -70,7 +72,7 @@ namespace SharedLibrary.Services
|
||||
.Where(expression)
|
||||
.Where(p => p.Active)
|
||||
.ToList();
|
||||
});
|
||||
});*/
|
||||
}
|
||||
|
||||
public Task<EFPenalty> Get(int entityID)
|
||||
|
@ -20,6 +20,7 @@ namespace SharedLibrary
|
||||
public static class Utilities
|
||||
{
|
||||
public static string OperatingDirectory = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + Path.DirectorySeparatorChar;
|
||||
public static readonly Task CompletedTask = Task.FromResult(false);
|
||||
|
||||
//Get string with specified number of spaces -- really only for visual output
|
||||
public static String GetSpaces(int Num)
|
||||
@ -52,7 +53,7 @@ namespace SharedLibrary
|
||||
return newStr;
|
||||
}
|
||||
|
||||
public static List<Player> PlayersFromStatus(String[] Status)
|
||||
public static List<Player> PlayersFromStatus(string[] Status)
|
||||
{
|
||||
List<Player> StatusPlayers = new List<Player>();
|
||||
|
||||
|
@ -40,7 +40,7 @@ namespace IW4MAdmin
|
||||
if (type == LogType.Error || type == LogType.Verbose)
|
||||
Console.WriteLine(LogLine);
|
||||
//if (type != LogType.Debug)
|
||||
File.AppendAllText(FileName, LogLine + Environment.NewLine);
|
||||
File.AppendAllText(FileName, $"{LogLine}{Environment.NewLine}");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -57,8 +57,15 @@ namespace IW4MAdmin
|
||||
PrivilegedClients = new Dictionary<int, Player>();
|
||||
ServerEventOccurred += EventAPI.OnServerEventOccurred;
|
||||
ConfigHandler = new BaseConfigurationHandler<ApplicationConfiguration>("IW4MAdminSettings");
|
||||
Console.CancelKeyPress += new ConsoleCancelEventHandler(OnCancelKey);
|
||||
}
|
||||
|
||||
private void OnCancelKey(object sender, ConsoleCancelEventArgs args)
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
|
||||
|
||||
public IList<Server> GetServers()
|
||||
{
|
||||
return Servers;
|
||||
@ -305,5 +312,7 @@ namespace IW4MAdmin
|
||||
public PenaltyService GetPenaltyService() => PenaltySvc;
|
||||
|
||||
public IConfigurationHandler<ApplicationConfiguration> GetApplicationSettings() => ConfigHandler;
|
||||
|
||||
public IDictionary<int, Player> GetPrivilegedClients() => PrivilegedClients;
|
||||
}
|
||||
}
|
||||
|
@ -788,7 +788,7 @@ namespace IW4MAdmin
|
||||
CurrentMap = Maps.Find(m => m.Name == mapname) ?? new Map() { Alias = mapname, Name = mapname };
|
||||
|
||||
// todo: make this more efficient
|
||||
((ApplicationManager)(Manager)).PrivilegedClients = new Dictionary<int, Player>();
|
||||
/*((ApplicationManager)(Manager)).PrivilegedClients = new Dictionary<int, Player>();
|
||||
var ClientSvc = new ClientService();
|
||||
var ipList = (await ClientSvc.Find(c => c.Level > Player.Permission.Trusted))
|
||||
.Select(c => new
|
||||
@ -818,7 +818,7 @@ namespace IW4MAdmin
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
if (E.Type == Event.GType.MapEnd)
|
||||
|
@ -2,6 +2,7 @@
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using System.Security.Claims;
|
||||
using System;
|
||||
|
||||
namespace WebfrontCore.Controllers
|
||||
{
|
||||
@ -15,23 +16,37 @@ namespace WebfrontCore.Controllers
|
||||
return Unauthorized();
|
||||
}
|
||||
|
||||
var client = IW4MAdmin.Program.ServerManager.PrivilegedClients[userId];
|
||||
string[] hashedPassword = await Task.FromResult(SharedLibrary.Helpers.Hashing.Hash(password, client.PasswordSalt));
|
||||
|
||||
if (hashedPassword[0] == client.Password)
|
||||
try
|
||||
{
|
||||
var claims = new[]
|
||||
var client = IW4MAdmin.Program.ServerManager.PrivilegedClients[userId];
|
||||
string[] hashedPassword = await Task.FromResult(SharedLibrary.Helpers.Hashing.Hash(password, client.PasswordSalt));
|
||||
|
||||
if (hashedPassword[0] == client.Password)
|
||||
{
|
||||
var claims = new[]
|
||||
{
|
||||
new Claim(ClaimTypes.NameIdentifier, client.Name),
|
||||
new Claim(ClaimTypes.Role, client.Level.ToString()),
|
||||
new Claim(ClaimTypes.Sid, client.ClientId.ToString())
|
||||
};
|
||||
|
||||
var claimsIdentity = new ClaimsIdentity(claims, "login");
|
||||
var claimsPrinciple = new ClaimsPrincipal(claimsIdentity);
|
||||
await HttpContext.Authentication.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, claimsPrinciple);
|
||||
var claimsIdentity = new ClaimsIdentity(claims, "login");
|
||||
var claimsPrinciple = new ClaimsPrincipal(claimsIdentity);
|
||||
await HttpContext.Authentication.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, claimsPrinciple, new Microsoft.AspNetCore.Http.Authentication.AuthenticationProperties()
|
||||
{
|
||||
AllowRefresh = true,
|
||||
ExpiresUtc = DateTime.UtcNow.AddDays(30),
|
||||
IsPersistent = true,
|
||||
IssuedUtc = DateTime.UtcNow
|
||||
});
|
||||
|
||||
return Ok();
|
||||
return Ok();
|
||||
}
|
||||
}
|
||||
|
||||
catch (Exception)
|
||||
{
|
||||
return Unauthorized();
|
||||
}
|
||||
|
||||
return Unauthorized();
|
||||
|
@ -82,7 +82,7 @@ namespace WebfrontCore.Controllers
|
||||
{
|
||||
new InputInfo()
|
||||
{
|
||||
Name = "UserID"
|
||||
Name = "User ID"
|
||||
},
|
||||
new InputInfo()
|
||||
{
|
||||
|
@ -30,8 +30,12 @@ namespace WebfrontCore.Controllers
|
||||
{
|
||||
|
||||
var server = Manager.Servers.First(s => s.GetHashCode() == serverId);
|
||||
var client = User.AsPlayer();
|
||||
client.CurrentServer = server;
|
||||
var client = new Player()
|
||||
{
|
||||
ClientId = User.ClientId,
|
||||
Level = User.Level,
|
||||
CurrentServer = server
|
||||
};
|
||||
|
||||
var remoteEvent = new Event(Event.GType.Say, command, client, null, server);
|
||||
|
||||
|
@ -35,7 +35,7 @@ namespace WebfrontCore.Controllers
|
||||
LevelInt = (int)p.Level
|
||||
}).ToList(),
|
||||
ChatHistory = s.ChatHistory.OrderBy(c => c.Time).Take((int)Math.Ceiling(s.ClientNum / 2.0)).ToArray(),
|
||||
PlayerHistory = s.PlayerHistory.ToArray()
|
||||
PlayerHistory = s.PlayerHistory.ToArray(),
|
||||
};
|
||||
return PartialView("_ClientActivity", serverInfo);
|
||||
}
|
||||
|
@ -55,7 +55,8 @@ namespace WebfrontCore
|
||||
AuthenticationScheme = CookieAuthenticationDefaults.AuthenticationScheme,
|
||||
AutomaticAuthenticate = true,
|
||||
AutomaticChallenge = true,
|
||||
LoginPath = "/Account/Login/"
|
||||
LoginPath = "/Account/Login/",
|
||||
ExpireTimeSpan = TimeSpan.FromDays(30),
|
||||
});
|
||||
|
||||
app.UseMvc(routes =>
|
||||
@ -65,7 +66,6 @@ namespace WebfrontCore
|
||||
template: "{controller=Home}/{action=Index}/{id?}");
|
||||
});
|
||||
|
||||
//app.UseBasicAuthentication(Authentication.Basic.Generate());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,8 @@ namespace WebfrontCore.ViewComponents
|
||||
Level = p.Level.ToString(),
|
||||
LevelInt = (int)p.Level
|
||||
}).ToList(),
|
||||
ChatHistory = s.ChatHistory.ToArray()
|
||||
ChatHistory = s.ChatHistory.ToArray(),
|
||||
Online = !s.Throttled
|
||||
}).ToList();
|
||||
return View("_List", serverInfo);
|
||||
}
|
||||
|
@ -17,5 +17,5 @@
|
||||
</div>
|
||||
|
||||
<div class="row server-history mb-4">
|
||||
<div class="server-history-row col-md-12" id="server_history_@Model.ID" data-serverid="@Model.ID" data-clienthistory='@Html.Raw(Json.Serialize(Model.PlayerHistory))'></div>
|
||||
<div class="server-history-row col-md-12" id="server_history_@Model.ID" data-serverid="@Model.ID" data-clienthistory='@Html.Raw(Json.Serialize(Model.PlayerHistory))' data-online="@Model.Online"></div>
|
||||
</div>
|
||||
|
@ -44,7 +44,6 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
<li class="nav-item text-center text-md-left"><a href="#" id="profile_action_login_btn" class="nav-link profile-action oi oi-key oi-fix-navbar w-100" title="Login" data-action="login" aria-hidden="true"></a></li>
|
||||
}
|
||||
</ul>
|
||||
@ -82,6 +81,8 @@
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="modal-message text-danger mb-3"></div>
|
||||
<div class="modal-body-content"></div>
|
||||
</div>
|
||||
<!--<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary">Action</button>
|
||||
|
@ -3,58 +3,72 @@
|
||||
}
|
||||
|
||||
.level-color-user, .level-color-guest {
|
||||
color: #fff;
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
}
|
||||
|
||||
.level-bgcolor-user, .level-bgcolor-guest {
|
||||
background-color: #fff;
|
||||
background-color: rgba(255, 255, 255, 0.85);
|
||||
}
|
||||
|
||||
.level-color-trusted {
|
||||
color: #749363;
|
||||
color: rgba(116,147,99,1);
|
||||
}
|
||||
|
||||
.level-bgcolor-trusted, .level-bgcolor-user {
|
||||
.level-bgcolor-trusted {
|
||||
background-color: #749363;
|
||||
background-color: rgba(116,147,99,1);
|
||||
}
|
||||
|
||||
.level-color-flagged {
|
||||
color: #fd9c38;
|
||||
color: rgba(253, 139, 22, 0.85);
|
||||
}
|
||||
|
||||
.level-bgcolor-flagged {
|
||||
background-color: #fd9c38;
|
||||
background-color: rgba(253, 139, 22, 0.85);
|
||||
}
|
||||
|
||||
.level-color-banned, .level-color-console {
|
||||
color: #ff6060;
|
||||
color: rgba(255, 69, 69, 0.85);
|
||||
}
|
||||
|
||||
.level-bgcolor-banned {
|
||||
background-color: #ff6060;
|
||||
background-color: rgba(255, 69, 69, 0.85);
|
||||
}
|
||||
|
||||
.level-color-moderator {
|
||||
color: #f0de8b;
|
||||
color: rgba(235, 211, 101, 0.75);
|
||||
}
|
||||
|
||||
.level-bgcolor-moderator {
|
||||
background-color: #f0de8b;
|
||||
background-color: rgba(235, 211, 101, 0.75);
|
||||
}
|
||||
|
||||
.level-color-administrator {
|
||||
color: #f1a8e8;
|
||||
color: rgba(236, 130, 222, 0.69);
|
||||
}
|
||||
|
||||
.level-bgcolor-administrator {
|
||||
background-color: #f1a8e8;
|
||||
background-color: rgba(236, 130, 222, 0.69);
|
||||
}
|
||||
|
||||
.level-color-senioradmin {
|
||||
color: #50bcc3;
|
||||
color: rgba(50, 177, 185, 0.85);
|
||||
}
|
||||
|
||||
.level-bgcolor-senioradmin {
|
||||
background-color: #50bcc3;
|
||||
background-color: rgba(50, 177, 185, 0.85);
|
||||
}
|
||||
|
||||
@ -72,26 +86,32 @@
|
||||
|
||||
.penalties-color-kick,
|
||||
.penalties-color-unban {
|
||||
color: #749363;
|
||||
color: rgba(116, 147, 99, 1);
|
||||
}
|
||||
|
||||
.penalties-color-report {
|
||||
color: #749363;
|
||||
color: rgba(116, 147, 99, 1);
|
||||
}
|
||||
|
||||
.penalties-color-warning {
|
||||
color: #f0de8b;
|
||||
color: rgba(235, 211, 101, 0.75);
|
||||
}
|
||||
|
||||
.penalties-color-tempban {
|
||||
color: #fd9c38;
|
||||
color: rgba(253, 139, 22, 0.85);
|
||||
}
|
||||
|
||||
.penalties-color-flag {
|
||||
color: #fd9c38;
|
||||
color: rgba(253, 139, 22, 0.85);
|
||||
}
|
||||
|
||||
.penalties-color-ban {
|
||||
color: #ff6060;
|
||||
color: rgba(255, 69, 69, 0.85);
|
||||
}
|
||||
|
||||
@ -122,6 +142,7 @@
|
||||
}
|
||||
|
||||
#profile_level > span.level {
|
||||
color: #f1a8e8;
|
||||
color: rgba(236, 130, 222, 0.69);
|
||||
font-weight: bold;
|
||||
font-size: 1.5em;
|
||||
@ -137,6 +158,7 @@
|
||||
}
|
||||
|
||||
#profile_level > span.level {
|
||||
color: #f1a8e8;
|
||||
color: rgba(236, 130, 222, 0.69);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
Binary file not shown.
@ -6,12 +6,14 @@
|
||||
const actionType = $(this).data('action');
|
||||
$.get('/Action/' + actionType + 'Form')
|
||||
.done(function (response) {
|
||||
$('#actionModal .modal-body').html(response);
|
||||
$('#actionModal .modal-message').fadeOut('fast');
|
||||
$('#actionModal .modal-body-content').html(response);
|
||||
$('#actionModal').modal();
|
||||
})
|
||||
.fail(function (jqxhr, textStatus, error) {
|
||||
$('#actionModal .modal-body').html('<span class="text-danger">' + error + '</span>');
|
||||
$('#actionModal .modal-message').text('Error &mdash ' + error);
|
||||
$('#actionModal').modal();
|
||||
$('#actionModal .modal-message').fadeIn('fast');
|
||||
});
|
||||
});
|
||||
|
||||
@ -29,18 +31,22 @@
|
||||
location.reload();
|
||||
}
|
||||
else {
|
||||
$('#actionModal .modal-body').html(response);
|
||||
$('#actionModal .modal-message').fadeOut('fast');
|
||||
$('#actionModal .modal-body-content').html(response);
|
||||
$('#actionModal').modal();
|
||||
}
|
||||
})
|
||||
.fail(function (jqxhr, textStatus, error) {
|
||||
if (jqxhr.status == 401) {
|
||||
$('#actionModal .modal-body').removeClass('text-danger');
|
||||
$('#actionModal .modal-body').prepend('<div class="text-danger mb-3">Invalid login credentials</div>');
|
||||
if ($('#actionModal .modal-message').text.length > 0) {
|
||||
$('#actionModal .modal-message').fadeOut('fast');
|
||||
}
|
||||
if (jqxhr.status === 401) {
|
||||
$('#actionModal .modal-message').text('Invalid login credentials');
|
||||
}
|
||||
else {
|
||||
$('#actionModal .modal-body').html('<span class="text-danger">Error — ' + error + '</span>');
|
||||
$('#actionModal .modal-message').text('Error — ' + error);
|
||||
}
|
||||
$('#actionModal .modal-message').fadeIn('fast');
|
||||
});
|
||||
});
|
||||
});
|
@ -1,4 +1,4 @@
|
||||
function getPlayerHistoryChart(playerHistory, i, width) {
|
||||
function getPlayerHistoryChart(playerHistory, i, width, color) {
|
||||
///////////////////////////////////////
|
||||
// thanks to canvasjs :(
|
||||
playerHistory.forEach(function (item, i) {
|
||||
@ -6,7 +6,7 @@
|
||||
});
|
||||
|
||||
return new CanvasJS.Chart(`server_history_${i}`, {
|
||||
backgroundColor: "#191919",
|
||||
backgroundColor: '#191919',
|
||||
height: 100,
|
||||
width: width,
|
||||
animationEnabled: true,
|
||||
@ -41,7 +41,7 @@
|
||||
data: [{
|
||||
showInLegend: false,
|
||||
type: "splineArea",
|
||||
color: "rgba(0, 122, 204, 0.432)",
|
||||
color: color,
|
||||
markerSize: 0,
|
||||
dataPoints: playerHistory
|
||||
}]
|
||||
@ -53,8 +53,9 @@ var charts = {};
|
||||
$('.server-history-row').each(function (index, element) {
|
||||
let clientHistory = $(this).data('clienthistory');
|
||||
let serverId = $(this).data('serverid');
|
||||
let color = $(this).data('online') === 'True' ? '#007acc' : '#ff6060'
|
||||
let width = $('.server-header').first().width();
|
||||
let historyChart = getPlayerHistoryChart(clientHistory, serverId, width);
|
||||
let historyChart = getPlayerHistoryChart(clientHistory, serverId, width, color);
|
||||
historyChart.render();
|
||||
charts[serverId] = historyChart;
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user