diff --git a/Application/Server.cs b/Application/Server.cs index 4a2cb7cc5..22fbf405f 100644 --- a/Application/Server.cs +++ b/Application/Server.cs @@ -94,7 +94,7 @@ namespace IW4MAdmin // client has connected in the past else { - player.LastConnection = DateTime.UtcNow; + client.LastConnection = DateTime.UtcNow; client.Connections += 1; var existingAlias = client.AliasLink.Children @@ -378,6 +378,11 @@ namespace IW4MAdmin Logger.WriteError(String.Format("The plugin \"{0}\" generated an error. ( see log )", P.Name)); Logger.WriteDebug(String.Format("Error Message: {0}", Except.Message)); Logger.WriteDebug(String.Format("Error Trace: {0}", Except.StackTrace)); + while (Except.InnerException != null) + { + Except = Except.InnerException; + Logger.WriteDebug($"Inner exception: {Except.Message}"); + } continue; } #endif diff --git a/Plugins/Stats/Cheat/Detection.cs b/Plugins/Stats/Cheat/Detection.cs index ee880ce86..dbac0820d 100644 --- a/Plugins/Stats/Cheat/Detection.cs +++ b/Plugins/Stats/Cheat/Detection.cs @@ -85,10 +85,11 @@ namespace IW4MAdmin.Plugins.Stats.Cheat // 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) @@ -196,7 +197,7 @@ namespace IW4MAdmin.Plugins.Stats.Cheat if (chestKills >= Thresholds.MediumSampleMinKills) { double marginOfError = Thresholds.GetMarginOfError(chestKills); - double lerpAmount = Math.Min(1.0, (chestKills - Thresholds.LowSampleMinKills) / (double)(Thresholds.HighSampleMinKills - Thresholds.LowSampleMinKills)); + double lerpAmount = Math.Min(1.0, (chestKills - Thresholds.MediumSampleMinKills) / (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; @@ -263,13 +264,13 @@ namespace IW4MAdmin.Plugins.Stats.Cheat { int totalChestKills = stats.HitLocations.Single(c => c.Location == IW4Info.HitLocation.left_arm_upper).HitCount; - if (totalChestKills >= 250) + if (totalChestKills >= 60) { double marginOfError = Thresholds.GetMarginOfError(totalChestKills); - double lerpAmount = Math.Min(1.0, (totalChestKills - Thresholds.LowSampleMinKills) / (double)(Thresholds.HighSampleMinKills - Thresholds.LowSampleMinKills)); + double lerpAmount = Math.Min(1.0, (totalChestKills - 60) / 250.0); // 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 chestAbdomenRatioLerpValueForFlag = Thresholds.Lerp(Thresholds.ChestAbdomenRatioThresholdHighSample(3.0), Thresholds.ChestAbdomenRatioThresholdHighSample(2), lerpAmount) + marginOfError; + double chestAbdomenLerpValueForBan = Thresholds.Lerp(Thresholds.ChestAbdomenRatioThresholdHighSample(4.0), Thresholds.ChestAbdomenRatioThresholdHighSample(4.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; diff --git a/Plugins/Stats/Helpers/StatManager.cs b/Plugins/Stats/Helpers/StatManager.cs index 94e3c90a1..1c68d387b 100644 --- a/Plugins/Stats/Helpers/StatManager.cs +++ b/Plugins/Stats/Helpers/StatManager.cs @@ -3,15 +3,13 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; + using SharedLibraryCore; using SharedLibraryCore.Helpers; using SharedLibraryCore.Interfaces; using SharedLibraryCore.Objects; -using SharedLibraryCore.Services; -using IW4MAdmin.Plugins.Stats.Models; using SharedLibraryCore.Commands; -using SharedLibraryCore.Configuration; -using IW4MAdmin.Plugins.Stats.Config; +using IW4MAdmin.Plugins.Stats.Models; namespace IW4MAdmin.Plugins.Stats.Helpers { @@ -209,6 +207,25 @@ namespace IW4MAdmin.Plugins.Stats.Helpers { var statsSvc = ContextThreads[serverId]; + + Vector3 vDeathOrigin = null; + Vector3 vKillOrigin = null; + + + try + { + vDeathOrigin = Vector3.Parse(deathOrigin); + vKillOrigin = Vector3.Parse(killOrigin); + } + + catch (FormatException) + { + Log.WriteWarning("Could not parse kill or death origin vector"); + Log.WriteDebug($"Kill - {killOrigin} Death - {deathOrigin}"); + await AddStandardKill(attacker, victim); + return; + } + var kill = new EFClientKill() { Active = true, @@ -216,8 +233,8 @@ namespace IW4MAdmin.Plugins.Stats.Helpers VictimId = victim.ClientId, ServerId = serverId, Map = ParseEnum.Get(map, typeof(IW4Info.MapName)), - DeathOrigin = Vector3.Parse(deathOrigin), - KillOrigin = Vector3.Parse(killOrigin), + DeathOrigin = vDeathOrigin, + KillOrigin = vKillOrigin, DeathType = ParseEnum.Get(type, typeof(IW4Info.MeansOfDeath)), Damage = Int32.Parse(damage), HitLoc = ParseEnum.Get(hitLoc, typeof(IW4Info.HitLocation)), diff --git a/SharedLibraryCore/Services/PenaltyService.cs b/SharedLibraryCore/Services/PenaltyService.cs index 8cc54a924..6198f4c4a 100644 --- a/SharedLibraryCore/Services/PenaltyService.cs +++ b/SharedLibraryCore/Services/PenaltyService.cs @@ -1,12 +1,10 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Threading.Tasks; using SharedLibraryCore.Database; using SharedLibraryCore.Database.Models; -using System.Linq.Expressions; using SharedLibraryCore.Dtos; using Microsoft.EntityFrameworkCore; diff --git a/SharedLibraryCore/Utilities.cs b/SharedLibraryCore/Utilities.cs index 03a800aed..1ab980bc1 100644 --- a/SharedLibraryCore/Utilities.cs +++ b/SharedLibraryCore/Utilities.cs @@ -395,7 +395,7 @@ namespace SharedLibraryCore await server.RemoteConnection.SendQueryAsync(QueryType.DVAR, dvarName) : await server.RemoteConnection.SendQueryAsync(QueryType.COMMAND, $"get {dvarName}"); - if (LineSplit.Length != 3) + if (LineSplit.Length < 3) { var e = new Exceptions.DvarException($"DVAR \"{dvarName}\" does not exist"); e.Data["dvar_name"] = dvarName; diff --git a/WebfrontCore/Controllers/ActionController.cs b/WebfrontCore/Controllers/ActionController.cs index ba4b74763..2bfc9abc8 100644 --- a/WebfrontCore/Controllers/ActionController.cs +++ b/WebfrontCore/Controllers/ActionController.cs @@ -21,6 +21,7 @@ namespace WebfrontCore.Controllers new InputInfo() { Name = "Reason", + Label = "Reason", Placeholder = "" } }, @@ -52,6 +53,7 @@ namespace WebfrontCore.Controllers new InputInfo() { Name = "Reason", + Label = "Reason", Placeholder = "" } }, diff --git a/WebfrontCore/Controllers/BaseController.cs b/WebfrontCore/Controllers/BaseController.cs index 4943f8d6b..dc2524aeb 100644 --- a/WebfrontCore/Controllers/BaseController.cs +++ b/WebfrontCore/Controllers/BaseController.cs @@ -27,16 +27,28 @@ namespace WebfrontCore.Controllers ClientId = -1 }; - try + if (HttpContext.Connection.RemoteIpAddress.ToString() != "127.0.0.1") { - User.ClientId = Convert.ToInt32(base.User.Claims.First(c => c.Type == ClaimTypes.Sid).Value); - User.Level = (Player.Permission)Enum.Parse(typeof(Player.Permission), base.User.Claims.First(c => c.Type == ClaimTypes.Role).Value); - User.CurrentAlias = new EFAlias() { Name = base.User.Claims.First(c => c.Type == ClaimTypes.NameIdentifier).Value }; + + + try + { + User.ClientId = Convert.ToInt32(base.User.Claims.First(c => c.Type == ClaimTypes.Sid).Value); + User.Level = (Player.Permission)Enum.Parse(typeof(Player.Permission), base.User.Claims.First(c => c.Type == ClaimTypes.Role).Value); + User.CurrentAlias = new EFAlias() { Name = base.User.Claims.First(c => c.Type == ClaimTypes.NameIdentifier).Value }; + } + + catch (InvalidOperationException) + { + + } } - catch (InvalidOperationException) + else { - + User.ClientId = 1; + User.Level = Player.Permission.Console; + User.CurrentAlias = new EFAlias() { Name = "IW4MAdmin" }; } Authorized = User.ClientId >= 0; diff --git a/WebfrontCore/Program.cs b/WebfrontCore/Program.cs index 968bb6e44..46d999efe 100644 --- a/WebfrontCore/Program.cs +++ b/WebfrontCore/Program.cs @@ -1,5 +1,6 @@ using System.IO; using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; using SharedLibraryCore.Interfaces; namespace WebfrontCore @@ -16,18 +17,28 @@ namespace WebfrontCore public static void Init(IManager mgr) { Manager = mgr; + BuildWebHost().Run(); } - public static IWebHost BuildWebHost() => - new WebHostBuilder() + public static IWebHost BuildWebHost() + { + + var config = new ConfigurationBuilder() + .AddJsonFile("WebfrontSettings.json", optional: false, reloadOnChange: false) + .AddEnvironmentVariables() + .Build(); + + return new WebHostBuilder() #if DEBUG .UseContentRoot(Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), @"..\..\..\..\", "WebfrontCore"))) #else .UseContentRoot(Directory.GetCurrentDirectory()) #endif + .UseUrls(config["Web:Address"]) .UseKestrel() .UseStartup() .Build(); + } } } diff --git a/WebfrontCore/Properties/launchSettings.json b/WebfrontCore/Properties/launchSettings.json index 233f0b8e2..a35479d6d 100644 --- a/WebfrontCore/Properties/launchSettings.json +++ b/WebfrontCore/Properties/launchSettings.json @@ -6,14 +6,5 @@ "applicationUrl": "http://localhost:61369/", "sslPort": 0 } - }, - "profiles": { - "IIS Express": { - "commandName": "IISExpress", - "launchBrowser": true, - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - } } -} +} \ No newline at end of file diff --git a/WebfrontCore/Startup.cs b/WebfrontCore/Startup.cs index 7bfa981f3..a3ef06d70 100644 --- a/WebfrontCore/Startup.cs +++ b/WebfrontCore/Startup.cs @@ -20,7 +20,7 @@ namespace WebfrontCore { var builder = new ConfigurationBuilder() .SetBasePath(env.ContentRootPath) - .AddJsonFile("WebfrontSettings.json", optional: true, reloadOnChange: false) + .AddJsonFile("WebfrontSettings.json", optional: false, reloadOnChange: false) .AddEnvironmentVariables(); Configuration = builder.Build(); @@ -42,6 +42,7 @@ namespace WebfrontCore options.AccessDeniedPath = "/"; options.LoginPath = "/"; }); + } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. diff --git a/WebfrontCore/Views/Client/Profile/Index.cshtml b/WebfrontCore/Views/Client/Profile/Index.cshtml index c40e2e655..956c7ada2 100644 --- a/WebfrontCore/Views/Client/Profile/Index.cshtml +++ b/WebfrontCore/Views/Client/Profile/Index.cshtml @@ -20,14 +20,14 @@
- @if (Model.LevelInt < (int)ViewBag.User.Level && - (SharedLibraryCore.Objects.Player.Permission)Model.LevelInt != SharedLibraryCore.Objects.Player.Permission.Banned) + @if (Model.LevelInt < (int)ViewBag.User.Level && + (SharedLibraryCore.Objects.Player.Permission)Model.LevelInt != SharedLibraryCore.Objects.Player.Permission.Banned) { } @if (Model.LevelInt < (int)ViewBag.User.Level && - (SharedLibraryCore.Objects.Player.Permission)Model.LevelInt == SharedLibraryCore.Objects.Player.Permission.Banned) + (SharedLibraryCore.Objects.Player.Permission)Model.LevelInt == SharedLibraryCore.Objects.Player.Permission.Banned) { } @@ -91,5 +91,7 @@ clientInfo.clientId = @Model.ClientId; clientInfo.Meta =@Html.Raw(Json.Serialize(@Model.Meta)); - -} \ No newline at end of file + + + +} diff --git a/WebfrontCore/Views/Console/Index.cshtml b/WebfrontCore/Views/Console/Index.cshtml index 51fe50899..f4351601f 100644 --- a/WebfrontCore/Views/Console/Index.cshtml +++ b/WebfrontCore/Views/Console/Index.cshtml @@ -2,7 +2,7 @@
- @Html.DropDownList("Server", Model.Select(s => new SelectListItem() { Text = s.Name, Value = s.ID.ToString() }).ToList(), new { @class = "form-control bg-dark text-light", id="console_server_select" }) + @Html.DropDownList("Server", Model.Select(s => new SelectListItem() { Text = s.Name, Value = s.ID.ToString() }).ToList(), new { @class = "form-control bg-dark text-light", id = "console_server_select" })
@@ -10,12 +10,14 @@
- +
@section scripts { - -} \ No newline at end of file + + + +} diff --git a/WebfrontCore/Views/Home/Index.cshtml b/WebfrontCore/Views/Home/Index.cshtml index a9d23e77b..3b21869b8 100644 --- a/WebfrontCore/Views/Home/Index.cshtml +++ b/WebfrontCore/Views/Home/Index.cshtml @@ -1,6 +1,7 @@ @await Component.InvokeAsync("ServerList") @section scripts { - - -} \ No newline at end of file + + + +} diff --git a/WebfrontCore/Views/Penalty/List.cshtml b/WebfrontCore/Views/Penalty/List.cshtml index 69a807675..c76ad4fe1 100644 --- a/WebfrontCore/Views/Penalty/List.cshtml +++ b/WebfrontCore/Views/Penalty/List.cshtml @@ -20,5 +20,7 @@ @section scripts { - + + + } \ No newline at end of file diff --git a/WebfrontCore/Views/Penalty/_Penalty.cshtml b/WebfrontCore/Views/Penalty/_Penalty.cshtml index d429999a8..8c38310e3 100644 --- a/WebfrontCore/Views/Penalty/_Penalty.cshtml +++ b/WebfrontCore/Views/Penalty/_Penalty.cshtml @@ -55,7 +55,7 @@ @Model.Type - + @Model.Offense diff --git a/WebfrontCore/Views/Shared/Error.cshtml b/WebfrontCore/Views/Shared/Error.cshtml index 296561067..62ec7637c 100644 --- a/WebfrontCore/Views/Shared/Error.cshtml +++ b/WebfrontCore/Views/Shared/Error.cshtml @@ -2,5 +2,5 @@ ViewData["Title"] = "Error"; } -

Sorry!

+

Sorry!

An error occurred while processing your request.

diff --git a/WebfrontCore/Views/Shared/_Layout.cshtml b/WebfrontCore/Views/Shared/_Layout.cshtml index 0894a04d7..3e4aea813 100644 --- a/WebfrontCore/Views/Shared/_Layout.cshtml +++ b/WebfrontCore/Views/Shared/_Layout.cshtml @@ -13,12 +13,12 @@ - + + - - + @@ -35,20 +35,20 @@ @if (!string.IsNullOrEmpty(ViewBag.DiscordLink)) - { - -} + { + + } @if (ViewBag.Authorized) - { - - -} -else -{ - -} + { + + + } + else + { + + }
@@ -56,6 +56,8 @@ else + +
`;$("#profile_meta").append(n)}});$(".ip-locate-link").click(function(n){n.preventDefault();const t=$(this).data("ip");$.getJSON("https://extreme-ip-lookup.com/json/"+t).done(function(n){$("#mainModal .modal-title").text(t);$("#mainModal .modal-body").text("");n.ipName.length>0&&$("#mainModal .modal-body").append("Hostname — "+n.ipName+"
");n.isp.length>0&&$("#mainModal .modal-body").append("ISP — "+n.isp+"
");n.org.length>0&&$("#mainModal .modal-body").append("Organization — "+n.org+"
");n.businessName.length>0&&$("#mainModal .modal-body").append("Business — "+n.businessName+"
");n.businessWebsite.length>0&&$("#mainModal .modal-body").append("Website — "+n.businessWebsite+"
");(n.city.length>0||n.region.length>0||n.country.length>0)&&$("#mainModal .modal-body").append("Location — ");n.city.length>0&&$("#mainModal .modal-body").append(n.city);n.region.length>0&&$("#mainModal .modal-body").append(", "+n.region);n.country.length>0&&$("#mainModal .modal-body").append(", "+n.country);$("#mainModal").modal()}).fail(function(n,t,i){$("#mainModal .modal-title").text("Error");$("#mainModal .modal-body").html('—'+i+"<\/span>");$("#mainModal").modal()})})});let mostRecentDate=0,currentStepAmount=0,lastStep="";charts={};$(".server-history-row").each(function(){let i=$(this).data("clienthistory"),n=$(this).data("serverid"),r=$(this).data("online")==="True"?"rgba(0, 122, 204, 0.432)":"#ff6060",u=$(".server-header").first().width(),t=getPlayerHistoryChart(i,n,u,r);t.render();charts[n]=t});$(window).resize(function(){$(".server-history-row").each(function(){let n=$(this).data("serverid");charts[n].options.width=$(".server-header").first().width();charts[n].render()})});setInterval(refreshClientActivity,2e3); \ No newline at end of file diff --git a/WebfrontCore/wwwroot/js/penalty.js b/WebfrontCore/wwwroot/js/penalty.js index 13f8ff503..6f5583fbd 100644 --- a/WebfrontCore/wwwroot/js/penalty.js +++ b/WebfrontCore/wwwroot/js/penalty.js @@ -1,53 +1,59 @@ let offset = 15; function loadMorePenalties() { + showLoader(); $.get('/Penalty/ListAsync', { offset: offset }) .done(function (response) { $('#penalty_table').append(response); + hideLoader(); + }) + .fail(function (jqxhr, statis, error) { + errorLoader(); }); offset += 15; } -/* -https://stackoverflow.com/questions/19731730/jquery-js-detect-users-scroll-attempt-without-any-window-overflow-to-scroll -*/ +if ($('#penalty_table').length == 1) { + /* + https://stackoverflow.com/questions/19731730/jquery-js-detect-users-scroll-attempt-without-any-window-overflow-to-scroll + */ -$('html').bind('mousewheel DOMMouseScroll', function (e) { - var delta = (e.originalEvent.wheelDelta || -e.originalEvent.detail); + $('html').bind('mousewheel DOMMouseScroll', function (e) { + var delta = (e.originalEvent.wheelDelta || -e.originalEvent.detail); - if (delta < 0 && !hasScrollBar) { - loadMorePenalties(); - } -}); - -/* -https://stackoverflow.com/questions/3898130/check-if-a-user-has-scrolled-to-the-bottom -*/ - -var _throttleTimer = null; -var _throttleDelay = 100; -var $window = $(window); -var $document = $(document); -var hasScrollBar = false; - -$document.ready(function () { - - $window - .off('scroll', ScrollHandler) - .on('scroll', ScrollHandler); - -}); - -function ScrollHandler(e) { - //throttle event: - hasScrollBar = true; - clearTimeout(_throttleTimer); - _throttleTimer = setTimeout(function () { - - //do work - if ($window.scrollTop() + $window.height() > $document.height() - 100) { + if (delta < 0 && !hasScrollBar) { loadMorePenalties(); } + }); - }, _throttleDelay); + /* + https://stackoverflow.com/questions/3898130/check-if-a-user-has-scrolled-to-the-bottom + */ + + var _throttleTimer = null; + var _throttleDelay = 100; + var $window = $(window); + var $document = $(document); + var hasScrollBar = false; + + $document.ready(function () { + + $window + .off('scroll', ScrollHandler) + .on('scroll', ScrollHandler); + }); + + function ScrollHandler(e) { + //throttle event: + hasScrollBar = true; + clearTimeout(_throttleTimer); + _throttleTimer = setTimeout(function () { + + //do work + if ($window.scrollTop() + $window.height() > $document.height() - 100) { + loadMorePenalties(); + } + + }, _throttleDelay); + } } \ No newline at end of file diff --git a/WebfrontCore/wwwroot/js/profile.js b/WebfrontCore/wwwroot/js/profile.js index 297fee9e1..d8f7c4a3a 100644 --- a/WebfrontCore/wwwroot/js/profile.js +++ b/WebfrontCore/wwwroot/js/profile.js @@ -2,6 +2,11 @@ let count = 1; $(document).ready(function () { + + if (typeof clientInfo === 'undefined') { + return false; + } + /* Expand alias tab if they have any */ @@ -66,9 +71,6 @@ $(document).ready(function () { if (response.isp.length > 0) { $('#mainModal .modal-body').append("ISP — " + response.isp + '
'); } - if (response.ipType.length > 0) { - $('#mainModal .modal-body').append("Type — " + response.ipType + '
'); - } if (response.org.length > 0) { $('#mainModal .modal-body').append("Organization — " + response.org + '
'); } diff --git a/WebfrontCore/wwwroot/js/server.min.js b/WebfrontCore/wwwroot/js/server.min.js deleted file mode 100644 index e69de29bb..000000000