add penalties for angle info
queue Tell/Say to prevent plugins from throwing exception when server is offlline fixed CPU usage issue over time sort penalties by type on webfront
This commit is contained in:
parent
f442f251f6
commit
3092a529e9
@ -23,7 +23,7 @@ namespace Application.RconParsers
|
||||
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,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,20}) +([0-9]+) +(\d+\.\d+\.\d+.\d+\:-*\d{1,5}|0+.0+:-*\d{1,5}) +(-*[0-9]+) +([0-9]+) *$";
|
||||
|
||||
public async Task<string[]> ExecuteCommandAsync(Connection connection, string command)
|
||||
{
|
||||
|
@ -559,6 +559,17 @@ namespace IW4MAdmin
|
||||
Logger.WriteInfo("Game ending...");
|
||||
}
|
||||
|
||||
if (E.Type == GameEvent.EventType.Tell)
|
||||
{
|
||||
await Tell(E.Message, E.Target);
|
||||
}
|
||||
|
||||
if (E.Type == GameEvent.EventType.Broadcast)
|
||||
{
|
||||
// this is a little ugly but I don't want to change the abstract class
|
||||
await E.Owner.ExecuteCommandAsync(E.Message);
|
||||
}
|
||||
|
||||
//todo: move
|
||||
while (ChatHistory.Count > Math.Ceiling((double)ClientNum / 2))
|
||||
ChatHistory.RemoveAt(0);
|
||||
|
@ -75,22 +75,7 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
|
||||
Kills++;
|
||||
AverageKillTime = (AverageKillTime + (DateTime.UtcNow - LastKill).TotalSeconds) / Kills;
|
||||
|
||||
#region SNAPSHOTS
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region VIEWANGLES
|
||||
/*double distance = Vector3.Distance(kill.KillOrigin, kill.DeathOrigin);
|
||||
double x = kill.KillOrigin.X + distance * Math.Cos(kill.ViewAngles.X.ToRadians()) * Math.Cos(kill.ViewAngles.Y.ToRadians());
|
||||
double y = kill.KillOrigin.Y + (distance * Math.Sin(kill.ViewAngles.X.ToRadians()) * Math.Cos(kill.ViewAngles.Y.ToRadians()));
|
||||
double z = kill.KillOrigin.Z + distance * Math.Sin((360.0f - kill.ViewAngles.Y).ToRadians());
|
||||
var trueVector = Vector3.Subtract(kill.KillOrigin, kill.DeathOrigin);
|
||||
var calculatedVector = Vector3.Subtract(kill.KillOrigin, new Vector3((float)x, (float)y, (float)z));
|
||||
double angle = trueVector.AngleBetween(calculatedVector);*/
|
||||
|
||||
|
||||
#region VIEWANGLES
|
||||
// make sure it's divisible by 2
|
||||
if (kill.AnglesList.Count % 2 == 0)
|
||||
{
|
||||
@ -127,6 +112,22 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
|
||||
hitLoc.HitOffsetAverage = 0f;
|
||||
}
|
||||
|
||||
var hitlocations = ClientStats.HitLocations
|
||||
.Where(hl => new List<int>() { 4, 5, 2, 3, }.Contains((int)hl.Location))
|
||||
.Where(hl => ClientStats.SessionKills > Thresholds.MediumSampleMinKills + 30);
|
||||
|
||||
double banAverage = hitlocations.Count() > 0 ? hitlocations.Average(c =>c.HitOffsetAverage) : 0;
|
||||
|
||||
if (banAverage > Thresholds.MaxOffset)
|
||||
{
|
||||
return new DetectionPenaltyResult()
|
||||
{
|
||||
ClientPenalty = Penalty.PenaltyType.Ban,
|
||||
RatioAmount = banAverage,
|
||||
KillCount = ClientStats.SessionKills,
|
||||
};
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
Log.WriteDebug($"MaxDistance={maxDistance}, PredictVsReal={realAgainstPredict}");
|
||||
#endif
|
||||
@ -137,28 +138,21 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
|
||||
if (currentStrain > ClientStats.MaxStrain)
|
||||
{
|
||||
ClientStats.MaxStrain = currentStrain;
|
||||
|
||||
if (ClientStats.MaxStrain > Thresholds.MaxStrain)
|
||||
{
|
||||
return new DetectionPenaltyResult()
|
||||
{
|
||||
ClientPenalty = Penalty.PenaltyType.Ban,
|
||||
RatioAmount = ClientStats.MaxStrain,
|
||||
KillCount = ClientStats.SessionKills,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
Log.WriteDebug($"Current Strain: {currentStrain}");
|
||||
#endif
|
||||
|
||||
/*if (kill.AdsPercent > 0.5 && kill.Distance > 3)
|
||||
{
|
||||
var hitLoc = ClientStats.HitLocations
|
||||
.First(hl => hl.Location == kill.HitLoc);
|
||||
float previousAverage = hitLoc.HitOffsetAverage;
|
||||
double newAverage = (previousAverage * (hitLoc.HitCount - 1) + angle) / hitLoc.HitCount;
|
||||
hitLoc.HitOffsetAverage = (float)newAverage;
|
||||
|
||||
if (double.IsNaN(hitLoc.HitOffsetAverage))
|
||||
{
|
||||
Log.WriteWarning("[Detection::ProcessKill] HitOffsetAvgerage NaN");
|
||||
Log.WriteDebug($"{previousAverage}-{hitLoc.HitCount}-{hitLoc}-{newAverage}");
|
||||
hitLoc.HitOffsetAverage = 0f;
|
||||
}
|
||||
}*/
|
||||
|
||||
LastKill = kill.When;
|
||||
|
||||
#endregion
|
||||
|
@ -31,6 +31,9 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
|
||||
public const int HighSampleMinKills = 100;
|
||||
public const double KillTimeThreshold = 0.2;
|
||||
|
||||
public const double MaxStrain = 0.4399;
|
||||
public const double MaxOffset = 4.789;
|
||||
|
||||
public static double GetMarginOfError(int numKills) => 1.6455 / Math.Sqrt(numKills);
|
||||
|
||||
public static double Lerp(double v1, double v2, double amount)
|
||||
|
@ -619,6 +619,10 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
||||
|
||||
Log.WriteDebug("Syncing servers");
|
||||
await statsSvc.ServerSvc.SaveChangesAsync();
|
||||
|
||||
statsSvc = null;
|
||||
// this should prevent the gunk for having a long lasting context.
|
||||
ContextThreads[serverId] = new ThreadSafeStatsService();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -40,7 +40,16 @@ namespace SharedLibraryCore.Objects
|
||||
|
||||
public async Task Tell(String Message)
|
||||
{
|
||||
await CurrentServer.Tell(Message, this);
|
||||
var e = new GameEvent()
|
||||
{
|
||||
Message = Message,
|
||||
Target = this,
|
||||
Owner = CurrentServer,
|
||||
Type = GameEvent.EventType.Tell,
|
||||
Data = Message
|
||||
};
|
||||
|
||||
CurrentServer.Manager.GetEventHandler().AddEvent(e);
|
||||
}
|
||||
|
||||
public async Task Kick(String Message, Player Sender)
|
||||
|
@ -127,6 +127,16 @@ namespace SharedLibraryCore
|
||||
{
|
||||
#if !DEBUG
|
||||
string formattedMessage = String.Format(RconParser.GetCommandPrefixes().Say, Message);
|
||||
|
||||
var e = new GameEvent()
|
||||
{
|
||||
Message = formattedMessage,
|
||||
Data = formattedMessage,
|
||||
Owner = this,
|
||||
Type = GameEvent.EventType.Broadcast,
|
||||
};
|
||||
|
||||
Manager.GetEventHandler().AddEvent(e);
|
||||
await this.ExecuteCommandAsync(formattedMessage);
|
||||
#else
|
||||
Logger.WriteVerbose(Message.StripColors());
|
||||
@ -141,7 +151,6 @@ namespace SharedLibraryCore
|
||||
/// <param name="Target">Player to send message to</param>
|
||||
public async Task Tell(String Message, Player Target)
|
||||
{
|
||||
|
||||
#if !DEBUG
|
||||
string formattedMessage = String.Format(RconParser.GetCommandPrefixes().Tell, Target.ClientNumber, Message);
|
||||
if (Target.ClientNumber > -1 && Message.Length > 0 && Target.Level != Player.Permission.Console)
|
||||
|
@ -98,13 +98,14 @@ namespace SharedLibraryCore.Services
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public async Task<IList<EFPenalty>> GetRecentPenalties(int count, int offset)
|
||||
public async Task<IList<EFPenalty>> GetRecentPenalties(int count, int offset, Penalty.PenaltyType showOnly = Penalty.PenaltyType.Any)
|
||||
{
|
||||
using (var context = new DatabaseContext())
|
||||
return await context.Penalties
|
||||
.AsNoTracking()
|
||||
.Include(p => p.Offender.CurrentAlias)
|
||||
.Include(p => p.Punisher.CurrentAlias)
|
||||
.Where(p => showOnly == Penalty.PenaltyType.Any ? p.Type != Penalty.PenaltyType.Any : p.Type == showOnly)
|
||||
.Where(p => p.Active)
|
||||
.OrderByDescending(p => p.When)
|
||||
.Skip(offset)
|
||||
|
@ -13,18 +13,22 @@ namespace WebfrontCore.Controllers
|
||||
{
|
||||
public class PenaltyController : BaseController
|
||||
{
|
||||
public IActionResult List()
|
||||
public IActionResult List(int showOnly = (int)SharedLibraryCore.Objects.Penalty.PenaltyType.Any)
|
||||
{
|
||||
ViewBag.Description = "List of all the recent penalties (bans, kicks, warnings) on IW4MAdmin";
|
||||
ViewBag.Title = "Client Penalties";
|
||||
ViewBag.Keywords = "IW4MAdmin, penalties, ban, kick, warns";
|
||||
|
||||
return View();
|
||||
return View((SharedLibraryCore.Objects.Penalty.PenaltyType)showOnly);
|
||||
}
|
||||
|
||||
public async Task<IActionResult> ListAsync(int offset = 0)
|
||||
public async Task<IActionResult> ListAsync(int offset = 0, int showOnly = (int)SharedLibraryCore.Objects.Penalty.PenaltyType.Any)
|
||||
{
|
||||
return await Task.FromResult(View("_List", offset));
|
||||
return await Task.FromResult(View("_List", new ViewModels.PenaltyFilterInfo()
|
||||
{
|
||||
Offset = offset,
|
||||
ShowOnly = (SharedLibraryCore.Objects.Penalty.PenaltyType)showOnly
|
||||
}));
|
||||
}
|
||||
|
||||
public async Task<IActionResult> PublicAsync()
|
||||
|
@ -10,9 +10,9 @@ namespace WebfrontCore.ViewComponents
|
||||
{
|
||||
public class PenaltyListViewComponent : ViewComponent
|
||||
{
|
||||
public async Task<IViewComponentResult> InvokeAsync(int offset)
|
||||
public async Task<IViewComponentResult> InvokeAsync(int offset, Penalty.PenaltyType showOnly)
|
||||
{
|
||||
var penalties = await Program.Manager.GetPenaltyService().GetRecentPenalties(12, offset);
|
||||
var penalties = await Program.Manager.GetPenaltyService().GetRecentPenalties(12, offset, showOnly);
|
||||
var penaltiesDto = penalties.Select(p => new PenaltyInfo()
|
||||
{
|
||||
OffenderId = p.OffenderId,
|
||||
|
13
WebfrontCore/ViewModels/PenaltyFilterInfo.cs
Normal file
13
WebfrontCore/ViewModels/PenaltyFilterInfo.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace WebfrontCore.ViewModels
|
||||
{
|
||||
public class PenaltyFilterInfo
|
||||
{
|
||||
public int Offset { get; set; }
|
||||
public SharedLibraryCore.Objects.Penalty.PenaltyType ShowOnly { get; set; }
|
||||
}
|
||||
}
|
@ -1,4 +1,37 @@
|
||||
<h4 class="pb-2 text-center ">@ViewBag.Title</h4>
|
||||
@model SharedLibraryCore.Objects.Penalty.PenaltyType
|
||||
|
||||
<h4 class="pb-2 text-center ">@ViewBag.Title</h4>
|
||||
<div class="row">
|
||||
<select class="form-control bg-dark text-muted" id="penalty_filter_selection">
|
||||
@{
|
||||
foreach (var penaltyType in Enum.GetValues(typeof(SharedLibraryCore.Objects.Penalty.PenaltyType)))
|
||||
{
|
||||
if ((SharedLibraryCore.Objects.Penalty.PenaltyType)penaltyType == SharedLibraryCore.Objects.Penalty.PenaltyType.Any)
|
||||
{
|
||||
if (Model == SharedLibraryCore.Objects.Penalty.PenaltyType.Any)
|
||||
{
|
||||
<option value="@Convert.ToInt32(penaltyType)" selected="selected" )>Show @penaltyType.ToString()</option>
|
||||
}
|
||||
else
|
||||
{
|
||||
<option value="@Convert.ToInt32(penaltyType)" )>Show @penaltyType.ToString()</option>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((SharedLibraryCore.Objects.Penalty.PenaltyType)penaltyType == Model)
|
||||
{
|
||||
<option value="@Convert.ToInt32(penaltyType)" selected="selected">Show only @penaltyType.ToString()s</option>
|
||||
}
|
||||
else
|
||||
{
|
||||
<option value="@Convert.ToInt32(penaltyType)" )>Show only @penaltyType.ToString()s</option>
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<div class="row">
|
||||
<table class="table table-striped">
|
||||
<thead class="d-none d-md-table-header-group">
|
||||
@ -11,7 +44,11 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="penalty_table" class="border-bottom bg-dark">
|
||||
@await Component.InvokeAsync("PenaltyList", new { offset = 0 })
|
||||
@await Component.InvokeAsync("PenaltyList", new WebfrontCore.ViewModels.PenaltyFilterInfo()
|
||||
{
|
||||
Offset = 0,
|
||||
ShowOnly = Model
|
||||
})
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="table d-table d-md-none">
|
||||
@ -24,4 +61,4 @@
|
||||
<environment include="Development">
|
||||
<script type="text/javascript" src="~/js/penalty.js"></script>
|
||||
</environment>
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,6 @@
|
||||
Layout = null;
|
||||
}
|
||||
|
||||
@model int
|
||||
@model WebfrontCore.ViewModels.PenaltyFilterInfo
|
||||
|
||||
@await Component.InvokeAsync("PenaltyList", new { offset = Model })
|
||||
@await Component.InvokeAsync("PenaltyList", new { offset = Model.Offset, showOnly = Model.ShowOnly })
|
@ -2,14 +2,14 @@
|
||||
"name": "asp.net",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"bootstrap": "v4.1.0",
|
||||
"bootstrap": "v4.1.1",
|
||||
"jquery": "3.3.1",
|
||||
"popper.js": "v1.12.9",
|
||||
"open-iconic": "1.1.1",
|
||||
"moment-timezone": "0.5.14"
|
||||
},
|
||||
"resolutions": {
|
||||
"bootstrap": "v4.1.0",
|
||||
"bootstrap": "v4.1.1",
|
||||
"jquery": "3.3.1"
|
||||
}
|
||||
}
|
||||
|
39
WebfrontCore/wwwroot/css/bootstrap-custom.scss
vendored
39
WebfrontCore/wwwroot/css/bootstrap-custom.scss
vendored
@ -1,4 +1,32 @@
|
||||
@import '../lib/bootstrap/scss/bootstrap.scss';
|
||||
$white: #fff !default;
|
||||
$blue: #007ACC !default;
|
||||
$red: rgba(255, 69, 69, 0.85) !default;
|
||||
$green: rgba(116,147,99, 1) !default;
|
||||
$orange: #fd7e14 !default;
|
||||
$primary: $blue !default;
|
||||
$secondary: $orange !default;
|
||||
$light: rgb(204, 204, 204) !default;
|
||||
$dark: rgb(24, 24, 24) !default;
|
||||
$body-bg: rgb(34,34,34) !default;
|
||||
$body-color: $white !default;
|
||||
$link-color: $white !default;
|
||||
$link-decoration: none !default;
|
||||
$link-hover-color: $primary !default;
|
||||
$link-hover-decoration: none !default;
|
||||
$font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Open Sans", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol" !default;
|
||||
|
||||
$navbar-padding-y: 0 !default;
|
||||
$navbar-nav-link-padding-x: 2rem !default;
|
||||
$font-size-base: 1rem !default; // Assumes the browser default, typically `16px`
|
||||
$h5-font-size: $font-size-base * 1.25 !default;
|
||||
$h1-font-size: $font-size-base * 2.5 !default;
|
||||
$navbar-brand-font-size: $h1-font-size !default;
|
||||
$navbar-toggler-font-size: $h5-font-size !default;
|
||||
|
||||
$navbar-dark-hover-color: $primary !default;
|
||||
|
||||
@import '../lib/bootstrap/scss/bootstrap.scss';
|
||||
|
||||
|
||||
/*custom variables*/
|
||||
|
||||
@ -83,10 +111,17 @@ a.link-inverse:hover {
|
||||
border-bottom-color: $orange;
|
||||
}
|
||||
|
||||
form * {
|
||||
form *, select {
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
|
||||
select {
|
||||
border-left: none !important;
|
||||
border-right: none !important;
|
||||
border-bottom: none !important;
|
||||
border-top: 2px solid rgba(0, 122, 204, 0.5) !important;
|
||||
}
|
||||
|
||||
.oi-fix-navbar {
|
||||
line-height: 1.5 !important;
|
||||
top: 0 !important;
|
||||
|
@ -5,6 +5,7 @@
|
||||
function showLoader() {
|
||||
$('.layout-loading-icon').attr('style', 'visibility:visible');
|
||||
$('.layout-loading-icon').removeClass('text-danger');
|
||||
$('.layout-loading-icon').removeClass('text-muted');
|
||||
$('.layout-loading-icon').fadeIn();
|
||||
}
|
||||
|
||||
@ -12,6 +13,10 @@ function errorLoader() {
|
||||
$('.layout-loading-icon').addClass('text-danger');
|
||||
}
|
||||
|
||||
function staleLoader() {
|
||||
$('.layout-loading-icon').addClass('text-muted');
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
hideLoader();
|
||||
|
||||
|
@ -8,9 +8,12 @@ function loadMorePenalties() {
|
||||
|
||||
showLoader();
|
||||
isLoading = true;
|
||||
$.get('/Penalty/ListAsync', { offset: offset })
|
||||
$.get('/Penalty/ListAsync', { offset: offset, showOnly : $('#penalty_filter_selection').val() })
|
||||
.done(function (response) {
|
||||
$('#penalty_table').append(response);
|
||||
if (response.trim().length === 0) {
|
||||
staleLoader();
|
||||
}
|
||||
hideLoader();
|
||||
isLoading = false;
|
||||
})
|
||||
@ -22,7 +25,13 @@ function loadMorePenalties() {
|
||||
}
|
||||
|
||||
if ($('#penalty_table').length === 1) {
|
||||
/*
|
||||
|
||||
$('#penalty_filter_selection').change(function() {
|
||||
// if (offset === 0) {
|
||||
location = location.href.split('?')[0] + "?showOnly=" + $('#penalty_filter_selection').val();
|
||||
// }
|
||||
});
|
||||
/*
|
||||
https://stackoverflow.com/questions/19731730/jquery-js-detect-users-scroll-attempt-without-any-window-overflow-to-scroll
|
||||
*/
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user