clean up the profanity determent plugin by using the Get/Set Additional properties

cleaned up the base event parser to not need the server object to generate the event
Hopefully prevent anticheat from freaking out when database connection is lost
This commit is contained in:
RaidMax 2019-05-13 10:36:11 -05:00
parent b99cc424e7
commit 5f588bb0f7
10 changed files with 169 additions and 212 deletions

View File

@ -75,27 +75,12 @@ namespace IW4MAdmin.Application.EventParsers
public string URLProtocolFormat { get; set; } = "CoD://{{ip}}:{{port}}";
public virtual GameEvent GetEvent(Server server, string logLine)
public virtual GameEvent GenerateGameEvent(string logLine)
{
logLine = Regex.Replace(logLine, @"([0-9]+:[0-9]+ |^[0-9]+ )", "").Trim();
string[] lineSplit = logLine.Split(';');
string eventType = lineSplit[0];
// this is a "custom callback" event
if (eventType == "JoinTeam")
{
var origin = server.GetClientsAsList()
.FirstOrDefault(c => c.NetworkId == lineSplit[1].ConvertGuidToLong());
return new GameEvent()
{
Type = GameEvent.EventType.JoinTeam,
Data = logLine,
Origin = origin,
Owner = server
};
}
if (eventType == "say" || eventType == "sayteam")
{
var matchResult = Regex.Match(logLine, Configuration.Say.Pattern);
@ -110,8 +95,7 @@ namespace IW4MAdmin.Application.EventParsers
if (message.Length > 0)
{
var origin = server.GetClientsAsList()
.First(c => c.NetworkId == matchResult.Groups[Configuration.Say.GroupMapping[ParserRegex.GroupType.OriginNetworkId]].ToString().ConvertGuidToLong());
long originId = matchResult.Groups[Configuration.Say.GroupMapping[ParserRegex.GroupType.OriginNetworkId]].ToString().ConvertGuidToLong();
if (message[0] == '!' || message[0] == '@')
{
@ -119,8 +103,8 @@ namespace IW4MAdmin.Application.EventParsers
{
Type = GameEvent.EventType.Command,
Data = message,
Origin = origin,
Owner = server,
Origin = new EFClient() { NetworkId = originId },
Target = Utilities.IW4MAdminClient(),
Message = message
};
}
@ -129,8 +113,8 @@ namespace IW4MAdmin.Application.EventParsers
{
Type = GameEvent.EventType.Say,
Data = message,
Origin = origin,
Owner = server,
Origin = new EFClient() { NetworkId = originId },
Target = Utilities.IW4MAdminClient(),
Message = message
};
}
@ -139,111 +123,47 @@ namespace IW4MAdmin.Application.EventParsers
if (eventType == "K")
{
if (!server.CustomCallback)
var match = Regex.Match(logLine, Configuration.Kill.Pattern);
if (match.Success)
{
var match = Regex.Match(logLine, Configuration.Kill.Pattern);
long originId = match.Groups[Configuration.Kill.GroupMapping[ParserRegex.GroupType.OriginNetworkId]].Value.ToString().ConvertGuidToLong(1);
long targetId = match.Groups[Configuration.Kill.GroupMapping[ParserRegex.GroupType.TargetNetworkId]].Value.ToString().ConvertGuidToLong();
if (match.Success)
return new GameEvent()
{
string originId = match.Groups[Configuration.Kill.GroupMapping[ParserRegex.GroupType.OriginNetworkId]].Value.ToString();
string targetId = match.Groups[Configuration.Kill.GroupMapping[ParserRegex.GroupType.TargetNetworkId]].Value.ToString();
var origin = !string.IsNullOrEmpty(originId) ? server.GetClientsAsList()
.First(c => c.NetworkId == originId.ConvertGuidToLong()) :
Utilities.IW4MAdminClient(server);
var target = !string.IsNullOrEmpty(targetId) ? server.GetClientsAsList()
.First(c => c.NetworkId == targetId.ConvertGuidToLong()) :
Utilities.IW4MAdminClient(server);
return new GameEvent()
{
Type = GameEvent.EventType.Kill,
Data = logLine,
Origin = origin,
Target = target,
Owner = server
};
}
Type = GameEvent.EventType.Kill,
Data = logLine,
Origin = new EFClient() { NetworkId = originId },
Target = new EFClient() { NetworkId = targetId },
};
}
}
if (eventType == "ScriptKill")
{
long originId = lineSplit[1].ConvertGuidToLong();
long targetId = lineSplit[2].ConvertGuidToLong();
var origin = originId == long.MinValue ? Utilities.IW4MAdminClient(server) :
server.GetClientsAsList().First(c => c.NetworkId == originId);
var target = targetId == long.MinValue ? Utilities.IW4MAdminClient(server) :
server.GetClientsAsList().FirstOrDefault(c => c.NetworkId == targetId) ?? Utilities.IW4MAdminClient(server);
return new GameEvent()
{
Type = GameEvent.EventType.ScriptKill,
Data = logLine,
Origin = origin,
Target = target,
Owner = server
};
}
if (eventType == "ScriptDamage")
{
long originId = lineSplit[1].ConvertGuidToLong();
long targetId = lineSplit[2].ConvertGuidToLong();
var origin = originId == long.MinValue ? Utilities.IW4MAdminClient(server) :
server.GetClientsAsList().First(c => c.NetworkId == originId);
var target = targetId == long.MinValue ? Utilities.IW4MAdminClient(server) :
server.GetClientsAsList().FirstOrDefault(c => c.NetworkId == targetId) ?? Utilities.IW4MAdminClient(server);
return new GameEvent()
{
Type = GameEvent.EventType.ScriptDamage,
Data = logLine,
Origin = origin,
Target = target,
Owner = server
};
}
// damage
if (eventType == "D")
{
if (!server.CustomCallback)
{
var regexMatch = Regex.Match(logLine, Configuration.Damage.Pattern);
if (regexMatch.Success)
{
string originId = regexMatch.Groups[Configuration.Damage.GroupMapping[ParserRegex.GroupType.OriginNetworkId]].ToString();
string targetId = regexMatch.Groups[Configuration.Damage.GroupMapping[ParserRegex.GroupType.TargetNetworkId]].ToString();
var origin = !string.IsNullOrEmpty(originId) ? server.GetClientsAsList()
.First(c => c.NetworkId == originId.ConvertGuidToLong()) :
Utilities.IW4MAdminClient(server);
var target = !string.IsNullOrEmpty(targetId) ? server.GetClientsAsList()
.First(c => c.NetworkId == targetId.ConvertGuidToLong()) :
Utilities.IW4MAdminClient(server);
long originId = regexMatch.Groups[Configuration.Damage.GroupMapping[ParserRegex.GroupType.OriginNetworkId]].ToString().ConvertGuidToLong(1);
long targetId = regexMatch.Groups[Configuration.Damage.GroupMapping[ParserRegex.GroupType.TargetNetworkId]].ToString().ConvertGuidToLong();
return new GameEvent()
{
Type = GameEvent.EventType.Damage,
Data = logLine,
Origin = origin,
Target = target,
Owner = server
Origin = new EFClient() { NetworkId = originId },
Target = new EFClient() { NetworkId = targetId }
};
}
}
}
// join
if (eventType == "J")
{
var regexMatch = Regex.Match(logLine, Configuration.Join.Pattern);
if (regexMatch.Success)
{
bool isBot = regexMatch.Groups[Configuration.Join.GroupMapping[ParserRegex.GroupType.OriginNetworkId]].ToString().Contains("bot");
@ -252,7 +172,6 @@ namespace IW4MAdmin.Application.EventParsers
{
Type = GameEvent.EventType.PreConnect,
Data = logLine,
Owner = server,
Origin = new EFClient()
{
CurrentAlias = new EFAlias()
@ -262,9 +181,9 @@ namespace IW4MAdmin.Application.EventParsers
NetworkId = regexMatch.Groups[Configuration.Join.GroupMapping[ParserRegex.GroupType.OriginNetworkId]].ToString().ConvertGuidToLong(),
ClientNumber = Convert.ToInt32(regexMatch.Groups[Configuration.Join.GroupMapping[ParserRegex.GroupType.OriginClientNumber]].ToString()),
State = EFClient.ClientState.Connecting,
CurrentServer = server,
IsBot = isBot
}
},
Target = Utilities.IW4MAdminClient()
};
}
}
@ -278,7 +197,6 @@ namespace IW4MAdmin.Application.EventParsers
{
Type = GameEvent.EventType.PreDisconnect,
Data = logLine,
Owner = server,
Origin = new EFClient()
{
CurrentAlias = new EFAlias()
@ -288,7 +206,8 @@ namespace IW4MAdmin.Application.EventParsers
NetworkId = regexMatch.Groups[Configuration.Quit.GroupMapping[ParserRegex.GroupType.OriginNetworkId]].ToString().ConvertGuidToLong(),
ClientNumber = Convert.ToInt32(regexMatch.Groups[Configuration.Quit.GroupMapping[ParserRegex.GroupType.OriginClientNumber]].ToString()),
State = EFClient.ClientState.Disconnecting
}
},
Target = Utilities.IW4MAdminClient()
};
}
}
@ -299,9 +218,8 @@ namespace IW4MAdmin.Application.EventParsers
{
Type = GameEvent.EventType.MapEnd,
Data = lineSplit[0],
Origin = Utilities.IW4MAdminClient(server),
Target = Utilities.IW4MAdminClient(server),
Owner = server
Origin = Utilities.IW4MAdminClient(),
Target = Utilities.IW4MAdminClient(),
};
}
@ -313,19 +231,59 @@ namespace IW4MAdmin.Application.EventParsers
{
Type = GameEvent.EventType.MapChange,
Data = lineSplit[0],
Origin = Utilities.IW4MAdminClient(server),
Target = Utilities.IW4MAdminClient(server),
Owner = server,
Origin = Utilities.IW4MAdminClient(),
Target = Utilities.IW4MAdminClient(),
Extra = dump.DictionaryFromKeyValue()
};
}
// this is a custom event printed out by _customcallbacks.gsc (used for team balance)
if (eventType == "JoinTeam")
{
return new GameEvent()
{
Type = GameEvent.EventType.JoinTeam,
Data = logLine,
Origin = new EFClient() { NetworkId = lineSplit[1].ConvertGuidToLong() },
Target = Utilities.IW4MAdminClient()
};
}
// this is a custom event printed out by _customcallbacks.gsc (used for anticheat)
if (eventType == "ScriptKill")
{
long originId = lineSplit[1].ConvertGuidToLong(1);
long targetId = lineSplit[2].ConvertGuidToLong();
return new GameEvent()
{
Type = GameEvent.EventType.ScriptKill,
Data = logLine,
Origin = new EFClient() { NetworkId = originId },
Target = new EFClient() { NetworkId = targetId }
};
}
// this is a custom event printed out by _customcallbacks.gsc (used for anticheat)
if (eventType == "ScriptDamage")
{
long originId = lineSplit[1].ConvertGuidToLong(1);
long targetId = lineSplit[2].ConvertGuidToLong();
return new GameEvent()
{
Type = GameEvent.EventType.ScriptDamage,
Data = logLine,
Origin = new EFClient() { NetworkId = originId },
Target = new EFClient() { NetworkId = targetId }
};
}
return new GameEvent()
{
Type = GameEvent.EventType.Unknown,
Origin = Utilities.IW4MAdminClient(server),
Target = Utilities.IW4MAdminClient(server),
Owner = server
Origin = Utilities.IW4MAdminClient(),
Target = Utilities.IW4MAdminClient()
};
}
}

View File

@ -3,7 +3,7 @@ using SharedLibraryCore.Interfaces;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Linq;
using System.Threading.Tasks;
namespace IW4MAdmin.Application.IO
@ -12,6 +12,7 @@ namespace IW4MAdmin.Application.IO
{
IEventParser Parser;
readonly string LogFile;
private bool? ignoreBots;
public long Length => new FileInfo(LogFile).Length;
@ -25,16 +26,20 @@ namespace IW4MAdmin.Application.IO
public async Task<ICollection<GameEvent>> ReadEventsFromLog(Server server, long fileSizeDiff, long startPosition)
{
if (!ignoreBots.HasValue)
{
ignoreBots = server.Manager.GetApplicationSettings().Configuration().IgnoreBots;
}
// allocate the bytes for the new log lines
List<string> logLines = new List<string>();
// open the file as a stream
using (var rd = new StreamReader(new FileStream(LogFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite), Utilities.EncodingType))
{
// todo: max async
// take the old start position and go back the number of new characters
rd.BaseStream.Seek(-fileSizeDiff, SeekOrigin.End);
string newLine;
while (!string.IsNullOrEmpty(newLine = await rd.ReadLineAsync()))
{
@ -51,10 +56,27 @@ namespace IW4MAdmin.Application.IO
{
try
{
// todo: catch elsewhere
events.Add(Parser.GetEvent(server, eventLine));
var gameEvent = Parser.GenerateGameEvent(eventLine);
// we don't want to add the even if ignoreBots is on and the event comes froma bot
if (!ignoreBots.Value || (ignoreBots.Value && (gameEvent.Origin.NetworkId != -1 || gameEvent.Target.NetworkId != -1)))
{
gameEvent.Owner = server;
// we need to pull the "live" versions of the client (only if the client id isn't IW4MAdmin
gameEvent.Origin = gameEvent.Origin.ClientId == 1 ? gameEvent.Origin : server.GetClientsAsList().First(_client => _client.NetworkId == gameEvent.Origin.NetworkId);
gameEvent.Target = gameEvent.Target.ClientId == 1 ? gameEvent.Target : server.GetClientsAsList().First(_client => _client.NetworkId == gameEvent.Target.NetworkId);
events.Add(gameEvent);
}
}
catch (InvalidOperationException)
{
if (!ignoreBots.Value)
{
server.Logger.WriteWarning("Could not find client in client list when parsing event line");
}
}
catch (Exception e)
{
server.Logger.WriteWarning("Could not properly parse event line");

View File

@ -4,6 +4,7 @@ using SharedLibraryCore;
using SharedLibraryCore.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using static SharedLibraryCore.Utilities;
@ -18,6 +19,7 @@ namespace IW4MAdmin.Application.IO
readonly IEventParser Parser;
readonly IGameLogServer Api;
readonly string logPath;
private bool? ignoreBots;
public GameLogReaderHttp(Uri gameLogServerUri, string logPath, IEventParser parser)
{
@ -35,6 +37,12 @@ namespace IW4MAdmin.Application.IO
#if DEBUG == true
server.Logger.WriteDebug($"Begin reading from http log");
#endif
if (!ignoreBots.HasValue)
{
ignoreBots = server.Manager.GetApplicationSettings().Configuration().IgnoreBots;
}
var events = new List<GameEvent>();
string b64Path = logPath;
var response = await Api.Log(b64Path);
@ -52,16 +60,33 @@ namespace IW4MAdmin.Application.IO
{
try
{
var e = Parser.GetEvent(server, eventLine);
var gameEvent = Parser.GenerateGameEvent(eventLine);
// we don't want to add the even if ignoreBots is on and the event comes froma bot
if (!ignoreBots.Value || (ignoreBots.Value && (gameEvent.Origin.NetworkId != -1 || gameEvent.Target.NetworkId != -1)))
{
gameEvent.Owner = server;
// we need to pull the "live" versions of the client (only if the client id isn't IW4MAdmin
gameEvent.Origin = gameEvent.Origin.ClientId == 1 ? gameEvent.Origin : server.GetClientsAsList().First(_client => _client.NetworkId == gameEvent.Origin.NetworkId);
gameEvent.Target = gameEvent.Target.ClientId == 1 ? gameEvent.Target : server.GetClientsAsList().First(_client => _client.NetworkId == gameEvent.Target.NetworkId);
events.Add(gameEvent);
}
#if DEBUG == true
server.Logger.WriteDebug($"Parsed event with id {e.Id} from http");
server.Logger.WriteDebug($"Parsed event with id {gameEvent.Id} from http");
#endif
events.Add(e);
}
catch (InvalidOperationException)
{
if (!ignoreBots.Value)
{
server.Logger.WriteWarning("Could not find client in client list when parsing event line");
}
}
catch (Exception e)
{
server.Logger.WriteWarning("Could not properly parse event line");
server.Logger.WriteWarning("Could not properly parse remote event line");
server.Logger.WriteDebug(e.Message);
server.Logger.WriteDebug(eventLine);
}

View File

@ -1,11 +1,9 @@
using System.Collections.Concurrent;
using System.Linq;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using SharedLibraryCore;
using SharedLibraryCore.Configuration;
using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Interfaces;
namespace IW4MAdmin.Plugins.ProfanityDeterment
@ -19,8 +17,6 @@ namespace IW4MAdmin.Plugins.ProfanityDeterment
public string Author => "RaidMax";
BaseConfigurationHandler<Configuration> Settings;
ConcurrentDictionary<int, Tracking> ProfanityCounts;
IManager Manager;
public Task OnEventAsync(GameEvent E, Server S)
{
@ -29,10 +25,7 @@ namespace IW4MAdmin.Plugins.ProfanityDeterment
if (E.Type == GameEvent.EventType.Connect)
{
if (!ProfanityCounts.TryAdd(E.Origin.ClientId, new Tracking(E.Origin)))
{
S.Logger.WriteWarning("Could not add client to profanity tracking");
}
E.Origin.SetAdditionalProperty("_profanityInfringements", 0);
var objectionalWords = Settings.Configuration().OffensiveWords;
bool containsObjectionalWord = objectionalWords.FirstOrDefault(w => E.Origin.Name.ToLower().Contains(w)) != null;
@ -54,10 +47,7 @@ namespace IW4MAdmin.Plugins.ProfanityDeterment
if (E.Type == GameEvent.EventType.Disconnect)
{
if (!ProfanityCounts.TryRemove(E.Origin.ClientId, out Tracking old))
{
S.Logger.WriteWarning("Could not remove client from profanity tracking");
}
E.Origin.SetAdditionalProperty("_profanityInfringements", 0);
}
if (E.Type == GameEvent.EventType.Say)
@ -78,17 +68,17 @@ namespace IW4MAdmin.Plugins.ProfanityDeterment
if (containsObjectionalWord)
{
var clientProfanity = ProfanityCounts[E.Origin.ClientId];
if (clientProfanity.Infringements >= Settings.Configuration().KickAfterInfringementCount)
int profanityInfringments = E.Origin.GetAdditionalProperty<int>("_profanityInfringements");
if (profanityInfringments >= Settings.Configuration().KickAfterInfringementCount)
{
clientProfanity.Client.Kick(Settings.Configuration().ProfanityKickMessage, Utilities.IW4MAdminClient(E.Owner));
E.Origin.Kick(Settings.Configuration().ProfanityKickMessage, Utilities.IW4MAdminClient(E.Owner));
}
else if (clientProfanity.Infringements < Settings.Configuration().KickAfterInfringementCount)
else if (profanityInfringments < Settings.Configuration().KickAfterInfringementCount)
{
clientProfanity.Infringements++;
clientProfanity.Client.Warn(Settings.Configuration().ProfanityWarningMessage, Utilities.IW4MAdminClient(E.Owner));
E.Origin.SetAdditionalProperty("_profanityInfringements", profanityInfringments + 1);
E.Origin.Warn(Settings.Configuration().ProfanityWarningMessage, Utilities.IW4MAdminClient(E.Owner));
}
}
}
@ -104,9 +94,6 @@ namespace IW4MAdmin.Plugins.ProfanityDeterment
Settings.Set((Configuration)new Configuration().Generate());
await Settings.Save();
}
ProfanityCounts = new ConcurrentDictionary<int, Tracking>();
Manager = manager;
}
public Task OnTickAsync(Server S) => Task.CompletedTask;

View File

@ -1,20 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Objects;
namespace IW4MAdmin.Plugins.ProfanityDeterment
{
class Tracking
{
public EFClient Client { get; private set; }
public int Infringements { get; set; }
public Tracking(EFClient client)
{
Client = client;
Infringements = 0;
}
}
}

View File

@ -568,7 +568,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
ctx.Set<EFClientKill>().Add(hit);
}
if (Plugin.Config.Configuration().EnableAntiCheat && !attacker.IsBot)
if (Plugin.Config.Configuration().EnableAntiCheat && !attacker.IsBot && attacker.ClientId != victim.ClientId)
{
if (clientDetection.QueuedHits.Count > Detection.QUEUE_COUNT)
{
@ -577,8 +577,10 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
clientDetection.QueuedHits = clientDetection.QueuedHits.OrderBy(_hits => _hits.TimeOffset).ToList();
var oldestHit = clientDetection.QueuedHits.First();
clientDetection.QueuedHits.RemoveAt(0);
await ApplyPenalty(clientDetection.ProcessHit(oldestHit, isDamage), clientDetection, attacker, ctx);
await ApplyPenalty(clientDetection.ProcessHit(oldestHit, isDamage), attacker, ctx);
}
await ApplyPenalty(clientDetection.ProcessTotalRatio(clientStats), attacker, ctx);
}
else
@ -586,7 +588,10 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
clientDetection.QueuedHits.Add(hit);
}
await ApplyPenalty(clientDetection.ProcessTotalRatio(clientStats), clientDetection, attacker, ctx);
if (clientDetection.Tracker.HasChanges)
{
SaveTrackedSnapshots(clientDetection, ctx);
}
}
ctx.Set<EFHitLocationCount>().UpdateRange(clientStats.HitLocations);
@ -604,7 +609,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
}
}
async Task ApplyPenalty(DetectionPenaltyResult penalty, Detection clientDetection, EFClient attacker, DatabaseContext ctx)
async Task ApplyPenalty(DetectionPenaltyResult penalty, EFClient attacker, DatabaseContext ctx)
{
var penaltyClient = Utilities.IW4MAdminClient(attacker.CurrentServer);
switch (penalty.ClientPenalty)
@ -626,11 +631,6 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
};
await attacker.Ban(Utilities.CurrentLocalization.LocalizationIndex["PLUGIN_STATS_CHEAT_DETECTED"], penaltyClient, false).WaitAsync(Utilities.DefaultCommandTimeout, attacker.CurrentServer.Manager.CancellationToken);
if (clientDetection.Tracker.HasChanges)
{
SaveTrackedSnapshots(clientDetection, ctx);
}
break;
case Penalty.PenaltyType.Flag:
if (attacker.Level != EFClient.Permission.User)
@ -643,11 +643,6 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
$"{penalty.Type}-{Math.Round(penalty.Value, 2)}@{penalty.HitCount}";
await attacker.Flag(flagReason, penaltyClient).WaitAsync(Utilities.DefaultCommandTimeout, attacker.CurrentServer.Manager.CancellationToken);
if (clientDetection.Tracker.HasChanges)
{
SaveTrackedSnapshots(clientDetection, ctx);
}
break;
}
}
@ -655,7 +650,8 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
void SaveTrackedSnapshots(Detection clientDetection, DatabaseContext ctx)
{
// todo: why does this cause duplicate primary key
var change = clientDetection.Tracker.GetNextChange();
_ = clientDetection.Tracker.GetNextChange();
EFACSnapshot change;
while ((change = clientDetection.Tracker.GetNextChange()) != default(EFACSnapshot))
{

View File

@ -80,16 +80,11 @@ namespace IW4MAdmin.Plugins.Stats
if (killInfo.Length >= 14 && !ShouldIgnoreEvent(E.Origin, E.Target))
{
// this treats "world" damage as self damage
if (E.Origin.ClientId <= 1)
if (E.Origin.ClientId == 1)
{
E.Origin = E.Target;
}
if (E.Target.ClientId <= 1)
{
E.Target = E.Origin;
}
await Manager.AddScriptHit(false, E.Time, E.Origin, E.Target, await StatManager.GetIdForServer(E.Owner), S.CurrentMap.Name, killInfo[7], killInfo[8],
killInfo[5], killInfo[6], killInfo[3], killInfo[4], killInfo[9], killInfo[10], killInfo[11], killInfo[12], killInfo[13], killInfo[14], killInfo[15]);
}
@ -98,16 +93,11 @@ namespace IW4MAdmin.Plugins.Stats
if (!E.Owner.CustomCallback && !ShouldIgnoreEvent(E.Origin, E.Target))
{
// this treats "world" damage as self damage
if (E.Origin.ClientId <= 1)
if (E.Origin.ClientId == 1)
{
E.Origin = E.Target;
}
if (E.Target.ClientId <= 1)
{
E.Target = E.Origin;
}
await Manager.AddStandardKill(E.Origin, E.Target);
}
break;
@ -115,16 +105,11 @@ namespace IW4MAdmin.Plugins.Stats
if (!E.Owner.CustomCallback && !ShouldIgnoreEvent(E.Origin, E.Target))
{
// this treats "world" damage as self damage
if (E.Origin.ClientId <= 1)
if (E.Origin.ClientId == 1)
{
E.Origin = E.Target;
}
if (E.Target.ClientId <= 1)
{
E.Target = E.Origin;
}
Manager.AddDamageEvent(E.Data, E.Origin.ClientId, E.Target.ClientId, await StatManager.GetIdForServer(E.Owner));
}
break;
@ -133,16 +118,11 @@ namespace IW4MAdmin.Plugins.Stats
if (killInfo.Length >= 14 && !ShouldIgnoreEvent(E.Origin, E.Target))
{
// this treats "world" damage as self damage
if (E.Origin.ClientId <= 1)
if (E.Origin.ClientId == 1)
{
E.Origin = E.Target;
}
if (E.Target.ClientId <= 1)
{
E.Target = E.Origin;
}
await Manager.AddScriptHit(true, E.Time, E.Origin, E.Target, await StatManager.GetIdForServer(E.Owner), S.CurrentMap.Name, killInfo[7], killInfo[8],
killInfo[5], killInfo[6], killInfo[3], killInfo[4], killInfo[9], killInfo[10], killInfo[11], killInfo[12], killInfo[13], killInfo[14], killInfo[15]);
}

View File

@ -7,11 +7,10 @@ namespace SharedLibraryCore.Interfaces
/// <summary>
/// Generates a game event based on log line input
/// </summary>
/// <param name="server">server the event occurred on</param>
/// <param name="logLine">single log line string</param>
/// <returns></returns>
/// todo: make this integrate without needing the server
GameEvent GetEvent(Server server, string logLine);
GameEvent GenerateGameEvent(string logLine);
/// <summary>
/// Get game specific folder prefix for log files
/// </summary>

View File

@ -268,11 +268,16 @@ namespace SharedLibraryCore
}
}
public static long ConvertGuidToLong(this string str)
public static long ConvertGuidToLong(this string str, long? fallback = null)
{
str = str.Substring(0, Math.Min(str.Length, 16));
var bot = Regex.Match(str, @"bot[0-9]+").Value;
if (string.IsNullOrWhiteSpace(str) && fallback.HasValue)
{
return fallback.Value;
}
// this is a special case for Plutonium T6
if (str.Length <= 11 &&
long.TryParse(str, NumberStyles.Integer, CultureInfo.InvariantCulture, out long id)) // 10 numeric characters + signed character

View File

@ -121,6 +121,11 @@ namespace WebfrontCore.Controllers
public async Task<IActionResult> FindAsync(string clientName)
{
if (string.IsNullOrWhiteSpace(clientName))
{
return StatusCode(400);
}
var clientsDto = await Manager.GetClientService().FindClientsByIdentifier(clientName);
ViewBag.Title = $"{clientsDto.Count} {Localization["WEBFRONT_CLIENT_SEARCH_MATCHING"]} \"{clientName}\"";