diff --git a/Application/ApplicationManager.cs b/Application/ApplicationManager.cs index 596f3ef00..0736c4edd 100644 --- a/Application/ApplicationManager.cs +++ b/Application/ApplicationManager.cs @@ -605,6 +605,11 @@ namespace IW4MAdmin.Application return _servers.SelectMany(s => s.Clients).ToList().Where(p => p != null).ToList(); } + public EFClient FindActiveClient(EFClient client) =>client.ClientNumber < 0 ? + GetActiveClients() + .FirstOrDefault(c => c.NetworkId == client.NetworkId) ?? client : + client; + public ClientService GetClientService() { return ClientSvc; diff --git a/Application/IW4MServer.cs b/Application/IW4MServer.cs index 525e43698..e26028791 100644 --- a/Application/IW4MServer.cs +++ b/Application/IW4MServer.cs @@ -725,11 +725,11 @@ namespace IW4MAdmin private async Task OnClientUpdate(EFClient origin) { - var client = GetClientsAsList().FirstOrDefault(_client => _client.Equals(origin)); + var client = Manager.GetActiveClients().FirstOrDefault(c => c.NetworkId == origin.NetworkId); if (client == null) { - ServerLogger.LogWarning("{origin} expected to exist in client list for update, but they do not", origin.ToString()); + ServerLogger.LogWarning("{Origin} expected to exist in client list for update, but they do not", origin.ToString()); return; } @@ -755,10 +755,10 @@ namespace IW4MAdmin } } - else if ((client.IPAddress != null && client.State == ClientState.Disconnecting) || + else if (client.IPAddress != null && client.State == ClientState.Disconnecting || client.Level == Permission.Banned) { - ServerLogger.LogWarning("{client} state is Unknown (probably kicked), but they are still connected. trying to kick again...", origin.ToString()); + ServerLogger.LogWarning("{Client} state is Unknown (probably kicked), but they are still connected. trying to kick again...", origin.ToString()); await client.CanConnect(client.IPAddress, Manager.GetApplicationSettings().Configuration().EnableImplicitAccountLinking); } } @@ -1321,12 +1321,9 @@ namespace IW4MAdmin public override async Task Warn(string reason, EFClient targetClient, EFClient targetOrigin) { // ensure player gets warned if command not performed on them in game - targetClient = targetClient.ClientNumber < 0 ? - Manager.GetActiveClients() - .FirstOrDefault(c => c.ClientId == targetClient?.ClientId) ?? targetClient : - targetClient; + var activeClient = Manager.FindActiveClient(targetClient); - var newPenalty = new EFPenalty() + var newPenalty = new EFPenalty { Type = EFPenalty.PenaltyType.Warning, Expires = DateTime.UtcNow, @@ -1336,31 +1333,28 @@ namespace IW4MAdmin Link = targetClient.AliasLink }; - ServerLogger.LogDebug("Creating warn penalty for {targetClient}", targetClient.ToString()); + ServerLogger.LogDebug("Creating warn penalty for {TargetClient}", targetClient.ToString()); await newPenalty.TryCreatePenalty(Manager.GetPenaltyService(), ServerLogger); - if (targetClient.IsIngame) + if (activeClient.IsIngame) { - if (targetClient.Warnings >= 4) + if (activeClient.Warnings >= 4) { - targetClient.Kick(loc["SERVER_WARNLIMT_REACHED"], Utilities.IW4MAdminClient(this)); + activeClient.Kick(loc["SERVER_WARNLIMT_REACHED"], Utilities.IW4MAdminClient(this)); return; } - // todo: move to translation sheet - string message = $"^1{loc["SERVER_WARNING"]} ^7[^3{targetClient.Warnings}^7]: ^3{targetClient.Name}^7, {reason}"; - targetClient.CurrentServer.Broadcast(message); + var message = loc["COMMANDS_WARNING_FORMAT"] + .FormatExt(activeClient.Warnings, activeClient.Name, reason); + activeClient.CurrentServer.Broadcast(message); } } public override async Task Kick(string reason, EFClient targetClient, EFClient originClient, EFPenalty previousPenalty) { - targetClient = targetClient.ClientNumber < 0 ? - Manager.GetActiveClients() - .FirstOrDefault(c => c.ClientId == targetClient?.ClientId) ?? targetClient : - targetClient; + var activeClient = Manager.FindActiveClient(targetClient); - var newPenalty = new EFPenalty() + var newPenalty = new EFPenalty { Type = EFPenalty.PenaltyType.Kick, Expires = DateTime.UtcNow, @@ -1370,77 +1364,64 @@ namespace IW4MAdmin Link = targetClient.AliasLink }; - ServerLogger.LogDebug("Creating kick penalty for {targetClient}", targetClient.ToString()); + ServerLogger.LogDebug("Creating kick penalty for {TargetClient}", targetClient.ToString()); await newPenalty.TryCreatePenalty(Manager.GetPenaltyService(), ServerLogger); - if (targetClient.IsIngame) + if (activeClient.IsIngame) { - var e = new GameEvent() + var gameEvent = new GameEvent { Type = GameEvent.EventType.PreDisconnect, - Origin = targetClient, + Origin = activeClient, Owner = this }; - Manager.AddEvent(e); - - var temporalClientId = targetClient.GetAdditionalProperty("ConnectionClientId"); - var parsedClientId = string.IsNullOrEmpty(temporalClientId) ? (int?)null : int.Parse(temporalClientId); - var clientNumber = parsedClientId ?? targetClient.ClientNumber; + Manager.AddEvent(gameEvent); var formattedKick = string.Format(RconParser.Configuration.CommandPrefixes.Kick, - clientNumber, + activeClient.TemporalClientNumber, _messageFormatter.BuildFormattedMessage(RconParser.Configuration, newPenalty, previousPenalty)); - await targetClient.CurrentServer.ExecuteCommandAsync(formattedKick); + ServerLogger.LogDebug("Executing tempban kick command for {ActiveClient}", activeClient.ToString()); + await activeClient.CurrentServer.ExecuteCommandAsync(formattedKick); } } - public override async Task TempBan(string Reason, TimeSpan length, EFClient targetClient, EFClient originClient) + public override async Task TempBan(string reason, TimeSpan length, EFClient targetClient, EFClient originClient) { // ensure player gets kicked if command not performed on them in the same server - targetClient = targetClient.ClientNumber < 0 ? - Manager.GetActiveClients() - .FirstOrDefault(c => c.ClientId == targetClient?.ClientId) ?? targetClient : - targetClient; + var activeClient = Manager.FindActiveClient(targetClient); - var newPenalty = new EFPenalty() + var newPenalty = new EFPenalty { Type = EFPenalty.PenaltyType.TempBan, Expires = DateTime.UtcNow + length, Offender = targetClient, - Offense = Reason, + Offense = reason, Punisher = originClient, Link = targetClient.AliasLink }; - ServerLogger.LogDebug("Creating tempban penalty for {targetClient}", targetClient.ToString()); + ServerLogger.LogDebug("Creating tempban penalty for {TargetClient}", targetClient.ToString()); await newPenalty.TryCreatePenalty(Manager.GetPenaltyService(), ServerLogger); - if (targetClient.IsIngame) + if (activeClient.IsIngame) { - var temporalClientId = targetClient.GetAdditionalProperty("ConnectionClientId"); - var parsedClientId = string.IsNullOrEmpty(temporalClientId) ? (int?)null : int.Parse(temporalClientId); - var clientNumber = parsedClientId ?? targetClient.ClientNumber; - var formattedKick = string.Format(RconParser.Configuration.CommandPrefixes.Kick, - clientNumber, + activeClient.TemporalClientNumber, _messageFormatter.BuildFormattedMessage(RconParser.Configuration, newPenalty)); - ServerLogger.LogDebug("Executing tempban kick command for {targetClient}", targetClient.ToString()); - await targetClient.CurrentServer.ExecuteCommandAsync(formattedKick); + ServerLogger.LogDebug("Executing tempban kick command for {ActiveClient}", activeClient.ToString()); + await activeClient.CurrentServer.ExecuteCommandAsync(formattedKick); } } public override async Task Ban(string reason, EFClient targetClient, EFClient originClient, bool isEvade = false) { // ensure player gets kicked if command not performed on them in the same server - targetClient = targetClient.ClientNumber < 0 ? - Manager.GetActiveClients() - .FirstOrDefault(c => c.ClientId == targetClient?.ClientId) ?? targetClient : - targetClient; + var activeClient = Manager.FindActiveClient(targetClient); - EFPenalty newPenalty = new EFPenalty() + var newPenalty = new EFPenalty { Type = EFPenalty.PenaltyType.Ban, Expires = null, @@ -1451,46 +1432,42 @@ namespace IW4MAdmin IsEvadedOffense = isEvade }; - ServerLogger.LogDebug("Creating ban penalty for {targetClient}", targetClient.ToString()); - targetClient.SetLevel(Permission.Banned, originClient); + ServerLogger.LogDebug("Creating ban penalty for {TargetClient}", targetClient.ToString()); + activeClient.SetLevel(Permission.Banned, originClient); await newPenalty.TryCreatePenalty(Manager.GetPenaltyService(), ServerLogger); - if (targetClient.IsIngame) + if (activeClient.IsIngame) { - ServerLogger.LogDebug("Attempting to kicking newly banned client {targetClient}", targetClient.ToString()); - - var temporalClientId = targetClient.GetAdditionalProperty("ConnectionClientId"); - var parsedClientId = string.IsNullOrEmpty(temporalClientId) ? (int?)null : int.Parse(temporalClientId); - var clientNumber = parsedClientId ?? targetClient.ClientNumber; + ServerLogger.LogDebug("Attempting to kicking newly banned client {ActiveClient}", activeClient.ToString()); var formattedString = string.Format(RconParser.Configuration.CommandPrefixes.Kick, - clientNumber, + activeClient.TemporalClientNumber, _messageFormatter.BuildFormattedMessage(RconParser.Configuration, newPenalty)); - await targetClient.CurrentServer.ExecuteCommandAsync(formattedString); + await activeClient.CurrentServer.ExecuteCommandAsync(formattedString); } } - override public async Task Unban(string reason, EFClient Target, EFClient Origin) + public override async Task Unban(string reason, EFClient targetClient, EFClient originClient) { - var unbanPenalty = new EFPenalty() + var unbanPenalty = new EFPenalty { Type = EFPenalty.PenaltyType.Unban, Expires = DateTime.Now, - Offender = Target, + Offender = targetClient, Offense = reason, - Punisher = Origin, + Punisher = originClient, When = DateTime.UtcNow, Active = true, - Link = Target.AliasLink + Link = targetClient.AliasLink }; - ServerLogger.LogDebug("Creating unban penalty for {targetClient}", Target.ToString()); - Target.SetLevel(Permission.User, Origin); - await Manager.GetPenaltyService().RemoveActivePenalties(Target.AliasLink.AliasLinkId); + ServerLogger.LogDebug("Creating unban penalty for {targetClient}", targetClient.ToString()); + targetClient.SetLevel(Permission.User, originClient); + await Manager.GetPenaltyService().RemoveActivePenalties(targetClient.AliasLink.AliasLinkId); await Manager.GetPenaltyService().Create(unbanPenalty); } - override public void InitializeTokens() + public override void InitializeTokens() { Manager.GetMessageTokens().Add(new MessageToken("TOTALPLAYERS", (Server s) => Task.Run(async () => (await Manager.GetClientService().GetTotalClientsAsync()).ToString()))); Manager.GetMessageTokens().Add(new MessageToken("VERSION", (Server s) => Task.FromResult(Application.Program.Version.ToString()))); diff --git a/SharedLibraryCore/Commands/CommandProcessing.cs b/SharedLibraryCore/Commands/CommandProcessing.cs index 5ebf36326..2d2dbedd3 100644 --- a/SharedLibraryCore/Commands/CommandProcessing.cs +++ b/SharedLibraryCore/Commands/CommandProcessing.cs @@ -83,6 +83,7 @@ namespace SharedLibraryCore.Commands var found = await Manager.GetClientService().Get(dbID); if (found != null) { + found = Manager.FindActiveClient(found); E.Target = found; E.Target.CurrentServer = E.Owner; E.Data = String.Join(" ", Args.Skip(1)); diff --git a/SharedLibraryCore/Interfaces/IManager.cs b/SharedLibraryCore/Interfaces/IManager.cs index 40b8f3e03..a82601086 100644 --- a/SharedLibraryCore/Interfaces/IManager.cs +++ b/SharedLibraryCore/Interfaces/IManager.cs @@ -7,7 +7,6 @@ using System.Threading; using System.Collections; using System; using System.Collections.Concurrent; -using Microsoft.Extensions.Logging; namespace SharedLibraryCore.Interfaces { @@ -23,6 +22,7 @@ namespace SharedLibraryCore.Interfaces IList GetCommands(); IList GetMessageTokens(); IList GetActiveClients(); + EFClient FindActiveClient(EFClient client); IConfigurationHandler GetApplicationSettings(); ClientService GetClientService(); PenaltyService GetPenaltyService(); diff --git a/SharedLibraryCore/PartialEntities/EFClient.cs b/SharedLibraryCore/PartialEntities/EFClient.cs index 4351f1ba9..679f0a577 100644 --- a/SharedLibraryCore/PartialEntities/EFClient.cs +++ b/SharedLibraryCore/PartialEntities/EFClient.cs @@ -683,6 +683,17 @@ namespace SharedLibraryCore.Database.Models set => SetAdditionalProperty(EFMeta.ClientTag, value); } + [NotMapped] + public int TemporalClientNumber + { + get + { + var temporalClientId = GetAdditionalProperty("ConnectionClientId"); + var parsedClientId = string.IsNullOrEmpty(temporalClientId) ? (int?) null : int.Parse(temporalClientId); + return parsedClientId ?? ClientNumber; + } + } + [NotMapped] private readonly SemaphoreSlim _processingEvent; diff --git a/SharedLibraryCore/Server.cs b/SharedLibraryCore/Server.cs index 9c0564616..75ea9c8cf 100644 --- a/SharedLibraryCore/Server.cs +++ b/SharedLibraryCore/Server.cs @@ -218,9 +218,9 @@ namespace SharedLibraryCore /// /// Temporarily ban a player ( default 1 hour ) from the server /// - /// Reason for banning the player + /// Reason for banning the player /// The player to ban - abstract public Task TempBan(String Reason, TimeSpan length, EFClient Target, EFClient Origin); + abstract public Task TempBan(String reason, TimeSpan length, EFClient Target, EFClient Origin); /// /// Perm ban a player from the server @@ -236,9 +236,9 @@ namespace SharedLibraryCore /// Unban a player by npID / GUID /// /// npID of the player - /// I don't remember what this is for + /// I don't remember what this is for /// - abstract public Task Unban(string reason, EFClient Target, EFClient Origin); + abstract public Task Unban(string reason, EFClient targetClient, EFClient originClient); /// /// Change the current searver map