diff --git a/Application/Application.csproj b/Application/Application.csproj index c781f1657..176c33985 100644 --- a/Application/Application.csproj +++ b/Application/Application.csproj @@ -6,7 +6,7 @@ 2.2.2 false RaidMax.IW4MAdmin.Application - 2.2.6.4 + 2.2.6.5 RaidMax Forever None IW4MAdmin @@ -31,8 +31,8 @@ true true - 2.2.6.4 - 2.2.6.4 + 2.2.6.5 + 2.2.6.5 diff --git a/Application/ApplicationManager.cs b/Application/ApplicationManager.cs index 2ca819573..a94b01af3 100644 --- a/Application/ApplicationManager.cs +++ b/Application/ApplicationManager.cs @@ -133,7 +133,7 @@ namespace IW4MAdmin.Application catch (Exception ex) { newEvent.FailReason = GameEvent.EventFailReason.Exception; - Logger.WriteError($"{Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_EXCEPTION"]} {newEvent.Owner}"); + Logger.WriteError(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_EXCEPTION"].FormatExt(newEvent.Owner)); Logger.WriteDebug(ex.GetExceptionInfo()); } diff --git a/Application/BuildScripts/PostPublish.bat b/Application/BuildScripts/PostPublish.bat index f9c4d92a1..0f159edc1 100644 --- a/Application/BuildScripts/PostPublish.bat +++ b/Application/BuildScripts/PostPublish.bat @@ -97,6 +97,16 @@ if "%CurrentConfiguration%" == "Release" ( if exist "%SolutionDir%Publish\Windows\refs" move "%SolutionDir%Publish\Windows\refs" "%SolutionDir%Publish\Windows\Lib\refs" ) +if "%CurrentConfiguration%" == "Prerelease" ( + echo PR-LOC + if not exist "%SolutionDir%Publish\WindowsPrerelease\Localization" md "%SolutionDir%Publish\WindowsPrerelease\Localization" +) + +if "%CurrentConfiguration%" == "Release" ( + echo R-LOC + if not exist "%SolutionDir%Publish\Windows\Localization" md "%SolutionDir%Publish\Windows\Localization" +) + echo making start scripts @(echo @echo off && echo @title IW4MAdmin && echo dotnet Lib\IW4MAdmin.dll && echo pause) > "%SolutionDir%Publish\WindowsPrerelease\StartIW4MAdmin.cmd" @(echo @echo off && echo @title IW4MAdmin && echo dotnet Lib\IW4MAdmin.dll && echo pause) > "%SolutionDir%Publish\Windows\StartIW4MAdmin.cmd" diff --git a/Application/IW4MServer.cs b/Application/IW4MServer.cs index b2524429e..30f1825dd 100644 --- a/Application/IW4MServer.cs +++ b/Application/IW4MServer.cs @@ -189,6 +189,10 @@ namespace IW4MAdmin if (E.Type == GameEvent.EventType.ConnectionRestored) { + if (Throttled) + { + Logger.WriteVerbose(loc["MANAGER_CONNECTION_REST"].FormatExt($"[{IP}:{Port}]")); + } Logger.WriteInfo("Connection restored to server, so we are no longer throttling the poll rate"); Throttled = false; } @@ -390,18 +394,27 @@ namespace IW4MAdmin { E.Data = E.Data.StripColors(); - if (E.Data.Length > 0) + if (E.Data?.Length > 0) { - // this may be a fix for a hard to reproduce null exception error - lock (ChatHistory) + string message = E.Data; + if (E.Data.IsQuickMessage()) { - ChatHistory.Add(new ChatInfo() + try { - Name = E.Origin.Name, - Message = E.Data ?? "NULL", - Time = DateTime.UtcNow - }); + message = Manager.GetApplicationSettings().Configuration() + .QuickMessages + .First(_qm => _qm.Game == GameName) + .Messages[E.Data.Substring(1)]; + } + catch { } } + + ChatHistory.Add(new ChatInfo() + { + Name = E.Origin.Name, + Message = message, + Time = DateTime.UtcNow + }); } } @@ -649,8 +662,6 @@ namespace IW4MAdmin if (ConnectionErrors > 0) { - Logger.WriteVerbose(loc["MANAGER_CONNECTION_REST"].FormatExt($"[{IP}:{Port}]")); - var _event = new GameEvent() { Type = GameEvent.EventType.ConnectionRestored, @@ -921,7 +932,7 @@ namespace IW4MAdmin #if !DEBUG else { - string formattedKick = String.Format(RconParser.Configuration.CommandPrefixes.Kick, Target.ClientNumber, $"{loc["SERVER_KICK_TEXT"]} - ^5{Reason}^7"); + string formattedKick = string.Format(RconParser.Configuration.CommandPrefixes.Kick, Target.ClientNumber, $"{loc["SERVER_KICK_TEXT"]} - ^5{Reason}^7"); await Target.CurrentServer.ExecuteCommandAsync(formattedKick); } #endif diff --git a/Plugins/Stats/Controllers/StatsController.cs b/Plugins/Stats/Controllers/StatsController.cs index 1874736ba..28554a4a5 100644 --- a/Plugins/Stats/Controllers/StatsController.cs +++ b/Plugins/Stats/Controllers/StatsController.cs @@ -91,7 +91,6 @@ namespace IW4MAdmin.Plugins.Stats.Web.Controllers .First(_qm => _qm.Game == message.ServerGame); message.Message = quickMessages.Messages[message.Message.Substring(1)]; message.IsQuickMessage = true; - } catch { } } diff --git a/Plugins/Stats/Helpers/StatManager.cs b/Plugins/Stats/Helpers/StatManager.cs index edc3a0d62..27a6b0988 100644 --- a/Plugins/Stats/Helpers/StatManager.cs +++ b/Plugins/Stats/Helpers/StatManager.cs @@ -13,7 +13,6 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; -using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; @@ -537,7 +536,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers return; } - // incase the add palyer event get delayed + // incase the add player event get delayed if (!Servers[serverId].PlayerStats.ContainsKey(attacker.ClientId)) { await AddPlayer(attacker); @@ -571,7 +570,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers ctx.Set().Add(hit); } - if (Plugin.Config.Configuration().EnableAntiCheat) + if (Plugin.Config.Configuration().EnableAntiCheat && !attacker.IsBot) { if (clientDetection.QueuedHits.Count > Detection.QUEUE_COUNT) { @@ -580,7 +579,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers clientDetection.QueuedHits = clientDetection.QueuedHits.OrderBy(_hits => _hits.TimeOffset).ToList(); var oldestHit = clientDetection.QueuedHits.First(); clientDetection.QueuedHits.RemoveAt(0); - ApplyPenalty(clientDetection.ProcessHit(oldestHit, isDamage), clientDetection, attacker, ctx); + await ApplyPenalty(clientDetection.ProcessHit(oldestHit, isDamage), clientDetection, attacker, ctx); } } @@ -589,7 +588,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers clientDetection.QueuedHits.Add(hit); } - ApplyPenalty(clientDetection.ProcessTotalRatio(clientStats), clientDetection, attacker, ctx); + await ApplyPenalty(clientDetection.ProcessTotalRatio(clientStats), clientDetection, attacker, ctx); } ctx.Set().UpdateRange(clientStats.HitLocations); @@ -607,8 +606,9 @@ namespace IW4MAdmin.Plugins.Stats.Helpers } } - void ApplyPenalty(DetectionPenaltyResult penalty, Detection clientDetection, EFClient attacker, DatabaseContext ctx) + async Task ApplyPenalty(DetectionPenaltyResult penalty, Detection clientDetection, EFClient attacker, DatabaseContext ctx) { + var penaltyClient = Utilities.IW4MAdminClient(attacker.CurrentServer); switch (penalty.ClientPenalty) { case Penalty.PenaltyType.Ban: @@ -616,22 +616,19 @@ namespace IW4MAdmin.Plugins.Stats.Helpers { break; } - attacker.Ban(Utilities.CurrentLocalization.LocalizationIndex["PLUGIN_STATS_CHEAT_DETECTED"], new EFClient() - { - ClientId = 1, - AdministeredPenalties = new List() - { - new EFPenalty() - { - AutomatedOffense = penalty.Type == Cheat.Detection.DetectionType.Bone ? - $"{penalty.Type}-{(int)penalty.Location}-{Math.Round(penalty.Value, 2)}@{penalty.HitCount}" : - $"{penalty.Type}-{Math.Round(penalty.Value, 2)}@{penalty.HitCount}", - } - }, - Level = EFClient.Permission.Console, - CurrentServer = attacker.CurrentServer, - }, false); + penaltyClient.AdministeredPenalties = new List() + { + new EFPenalty() + { + AutomatedOffense = penalty.Type == Detection.DetectionType.Bone ? + $"{penalty.Type}-{(int)penalty.Location}-{Math.Round(penalty.Value, 2)}@{penalty.HitCount}" : + $"{penalty.Type}-{Math.Round(penalty.Value, 2)}@{penalty.HitCount}", + } + }; + + await attacker.Ban(Utilities.CurrentLocalization.LocalizationIndex["PLUGIN_STATS_CHEAT_DETECTED"], penaltyClient, false).WaitAsync(); + if (clientDetection.Tracker.HasChanges) { SaveTrackedSnapshots(clientDetection, ctx); @@ -647,23 +644,17 @@ namespace IW4MAdmin.Plugins.Stats.Helpers $"{penalty.Type}-{(int)penalty.Location}-{Math.Round(penalty.Value, 2)}@{penalty.HitCount}" : $"{penalty.Type}-{Math.Round(penalty.Value, 2)}@{penalty.HitCount}"; - attacker.Flag(flagReason, new EFClient() - { - ClientId = 1, - Level = EFClient.Permission.Console, - CurrentServer = attacker.CurrentServer, - }); + await attacker.Flag(flagReason, penaltyClient).WaitAsync(); if (clientDetection.Tracker.HasChanges) { SaveTrackedSnapshots(clientDetection, ctx); } - break; } } - void SaveTrackedSnapshots(Cheat.Detection clientDetection, DatabaseContext ctx) + void SaveTrackedSnapshots(Detection clientDetection, DatabaseContext ctx) { // todo: why does this cause duplicate primary key var change = clientDetection.Tracker.GetNextChange(); diff --git a/Plugins/Stats/Plugin.cs b/Plugins/Stats/Plugin.cs index 211b8ecbd..3fade2cc1 100644 --- a/Plugins/Stats/Plugin.cs +++ b/Plugins/Stats/Plugin.cs @@ -5,6 +5,7 @@ using Microsoft.EntityFrameworkCore; using SharedLibraryCore; using SharedLibraryCore.Configuration; using SharedLibraryCore.Database; +using SharedLibraryCore.Database.Models; using SharedLibraryCore.Dtos; using SharedLibraryCore.Helpers; using SharedLibraryCore.Interfaces; @@ -76,13 +77,8 @@ namespace IW4MAdmin.Plugins.Stats break; case GameEvent.EventType.ScriptKill: string[] killInfo = (E.Data != null) ? E.Data.Split(';') : new string[0]; - if (killInfo.Length >= 14) + if (killInfo.Length >= 14 && !ShouldIgnoreEvent(E.Origin, E.Target)) { - if (E.Origin.ClientId <= 1 && E.Target.ClientId <= 1) - { - return; - } - // this treats "world" damage as self damage if (E.Origin.ClientId <= 1) { @@ -99,13 +95,8 @@ namespace IW4MAdmin.Plugins.Stats } break; case GameEvent.EventType.Kill: - if (!E.Owner.CustomCallback) + if (!E.Owner.CustomCallback && !ShouldIgnoreEvent(E.Origin, E.Target)) { - if (E.Origin.ClientId <= 1 && E.Target.ClientId <= 1) - { - return; - } - // this treats "world" damage as self damage if (E.Origin.ClientId <= 1) { @@ -121,13 +112,8 @@ namespace IW4MAdmin.Plugins.Stats } break; case GameEvent.EventType.Damage: - if (!E.Owner.CustomCallback) + if (!E.Owner.CustomCallback && !ShouldIgnoreEvent(E.Origin, E.Target)) { - if (E.Origin.ClientId <= 1 && E.Target.ClientId <= 1) - { - return; - } - // this treats "world" damage as self damage if (E.Origin.ClientId <= 1) { @@ -144,13 +130,8 @@ namespace IW4MAdmin.Plugins.Stats break; case GameEvent.EventType.ScriptDamage: killInfo = (E.Data != null) ? E.Data.Split(';') : new string[0]; - if (killInfo.Length >= 14) + if (killInfo.Length >= 14 && !ShouldIgnoreEvent(E.Origin, E.Target)) { - if (E.Origin.ClientId <= 1 && E.Target.ClientId <= 1) - { - return; - } - // this treats "world" damage as self damage if (E.Origin.ClientId <= 1) { @@ -500,5 +481,17 @@ namespace IW4MAdmin.Plugins.Stats await Manager.Sync(sv); } } + + /// + /// Indicates if the event should be ignored + /// (If the client id or target id is not a real client or the target/origin is a bot and ignore bots is turned on) + /// + /// + /// + /// + private bool ShouldIgnoreEvent(EFClient origin, EFClient target) + { + return ((origin.ClientId <= 1 && target.ClientId <= 1) || (target.IsBot || origin.IsBot) && ServerManager.GetApplicationSettings().Configuration().IgnoreBots); + } } } diff --git a/SharedLibraryCore/Server.cs b/SharedLibraryCore/Server.cs index 68102fa99..3bb26ba58 100644 --- a/SharedLibraryCore/Server.cs +++ b/SharedLibraryCore/Server.cs @@ -267,7 +267,7 @@ namespace SharedLibraryCore public override string ToString() { - return $"{IP}-{Port}"; + return $"{IP}:{Port}"; } protected async Task ScriptLoaded() diff --git a/SharedLibraryCore/Utilities.cs b/SharedLibraryCore/Utilities.cs index 18acdefac..8e451ffd3 100644 --- a/SharedLibraryCore/Utilities.cs +++ b/SharedLibraryCore/Utilities.cs @@ -269,6 +269,7 @@ namespace SharedLibraryCore public static long ConvertLong(this string str) { str = str.Substring(0, Math.Min(str.Length, 16)); + int maxBots = 18; long id; if (str.Length <= 11) // 10 numeric characters + signed character @@ -288,7 +289,7 @@ namespace SharedLibraryCore if (!string.IsNullOrEmpty(bot)) { // should set their GUID to the negation of their 1 based index (-1 - -18) - return -(Convert.ToInt64(bot.Substring(3)) + 1); + return -(Convert.ToInt64(bot.Substring(3)) + 1) % maxBots; } return long.MinValue; diff --git a/WebfrontCore/wwwroot/css/profile.css b/WebfrontCore/wwwroot/css/profile.css index 55cf2e012..64127515f 100644 --- a/WebfrontCore/wwwroot/css/profile.css +++ b/WebfrontCore/wwwroot/css/profile.css @@ -153,6 +153,8 @@ min-width: 8rem; min-height: 8rem; background-size: contain; + background-repeat: no-repeat; + background-position: center; } .profile-shortcode {