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 {