diff --git a/Plugins/Mute/Commands/MuteCommand.cs b/Plugins/Mute/Commands/MuteCommand.cs index 5d6dbabd6..82c4cd7e2 100644 --- a/Plugins/Mute/Commands/MuteCommand.cs +++ b/Plugins/Mute/Commands/MuteCommand.cs @@ -4,13 +4,16 @@ using SharedLibraryCore.Commands; using SharedLibraryCore.Configuration; using SharedLibraryCore.Interfaces; -namespace Mute.Commands; +namespace IW4MAdmin.Plugins.Mute.Commands; public class MuteCommand : Command { - public MuteCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, + private readonly MuteManager _muteManager; + + public MuteCommand(CommandConfiguration config, ITranslationLookup translationLookup, MuteManager muteManager) : base(config, translationLookup) { + _muteManager = muteManager; Name = "mute"; Description = translationLookup["PLUGINS_MUTE_COMMANDS_MUTE_DESC"]; Alias = "mu"; @@ -40,7 +43,7 @@ public class MuteCommand : Command return; } - if (await Plugin.MuteManager.Mute(gameEvent.Owner, gameEvent.Origin, gameEvent.Target, null, gameEvent.Data)) + if (await _muteManager.Mute(gameEvent.Owner, gameEvent.Origin, gameEvent.Target, null, gameEvent.Data)) { gameEvent.Origin.Tell(_translationLookup["PLUGINS_MUTE_COMMANDS_MUTE_MUTED"] .FormatExt(gameEvent.Target.CleanedName)); diff --git a/Plugins/Mute/Commands/MuteInfoCommand.cs b/Plugins/Mute/Commands/MuteInfoCommand.cs index 574f0e9f5..4622a0ce9 100644 --- a/Plugins/Mute/Commands/MuteInfoCommand.cs +++ b/Plugins/Mute/Commands/MuteInfoCommand.cs @@ -5,13 +5,16 @@ using SharedLibraryCore.Commands; using SharedLibraryCore.Configuration; using SharedLibraryCore.Interfaces; -namespace Mute.Commands; +namespace IW4MAdmin.Plugins.Mute.Commands; public class MuteInfoCommand : Command { - public MuteInfoCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, + private readonly MuteManager _muteManager; + + public MuteInfoCommand(CommandConfiguration config, ITranslationLookup translationLookup, MuteManager muteManager) : base(config, translationLookup) { + _muteManager = muteManager; Name = "muteinfo"; Description = translationLookup["PLUGINS_MUTE_COMMANDS_MUTEINFO_DESC"]; Alias = "mi"; @@ -30,7 +33,7 @@ public class MuteInfoCommand : Command public override async Task ExecuteAsync(GameEvent gameEvent) { - var currentMuteMeta = await Plugin.MuteManager.GetCurrentMuteState(gameEvent.Target); + var currentMuteMeta = await _muteManager.GetCurrentMuteState(gameEvent.Target); switch (currentMuteMeta.MuteState) { case MuteState.Muted when currentMuteMeta.Expiration is null: diff --git a/Plugins/Mute/Commands/TempMuteCommand.cs b/Plugins/Mute/Commands/TempMuteCommand.cs index 3263c1dcd..69a2999c9 100644 --- a/Plugins/Mute/Commands/TempMuteCommand.cs +++ b/Plugins/Mute/Commands/TempMuteCommand.cs @@ -5,15 +5,17 @@ using SharedLibraryCore.Commands; using SharedLibraryCore.Configuration; using SharedLibraryCore.Interfaces; -namespace Mute.Commands; +namespace IW4MAdmin.Plugins.Mute.Commands; public class TempMuteCommand : Command { + private readonly MuteManager _muteManager; private const string TempBanRegex = @"([0-9]+\w+)\ (.+)"; - public TempMuteCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, + public TempMuteCommand(CommandConfiguration config, ITranslationLookup translationLookup, MuteManager muteManager) : base(config, translationLookup) { + _muteManager = muteManager; Name = "tempmute"; Description = translationLookup["PLUGINS_MUTE_COMMANDS_TEMPMUTE_DESC"]; Alias = "tm"; @@ -54,7 +56,7 @@ public class TempMuteCommand : Command var expiration = DateTime.UtcNow + match.Groups[1].ToString().ParseTimespan(); var reason = match.Groups[2].ToString(); - if (await Plugin.MuteManager.Mute(gameEvent.Owner, gameEvent.Origin, gameEvent.Target, expiration, reason)) + if (await _muteManager.Mute(gameEvent.Owner, gameEvent.Origin, gameEvent.Target, expiration, reason)) { gameEvent.Origin.Tell(_translationLookup["PLUGINS_MUTE_COMMANDS_TEMPMUTE_TEMPMUTED"] .FormatExt(gameEvent.Target.CleanedName)); diff --git a/Plugins/Mute/Commands/UnmuteCommand.cs b/Plugins/Mute/Commands/UnmuteCommand.cs index 00ad125bc..e59c4334a 100644 --- a/Plugins/Mute/Commands/UnmuteCommand.cs +++ b/Plugins/Mute/Commands/UnmuteCommand.cs @@ -4,13 +4,16 @@ using SharedLibraryCore.Commands; using SharedLibraryCore.Configuration; using SharedLibraryCore.Interfaces; -namespace Mute.Commands; +namespace IW4MAdmin.Plugins.Mute.Commands; public class UnmuteCommand : Command { - public UnmuteCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, + private readonly MuteManager _muteManager; + + public UnmuteCommand(CommandConfiguration config, ITranslationLookup translationLookup, MuteManager muteManager) : base(config, translationLookup) { + _muteManager = muteManager; Name = "unmute"; Description = translationLookup["PLUGINS_MUTE_COMMANDS_UNMUTE_DESC"]; Alias = "um"; @@ -40,7 +43,7 @@ public class UnmuteCommand : Command return; } - if (await Plugin.MuteManager.Unmute(gameEvent.Owner, gameEvent.Origin, gameEvent.Target, gameEvent.Data)) + if (await _muteManager.Unmute(gameEvent.Owner, gameEvent.Origin, gameEvent.Target, gameEvent.Data)) { gameEvent.Origin.Tell(_translationLookup["PLUGINS_MUTE_COMMANDS_UNMUTE_UNMUTED"] .FormatExt(gameEvent.Target.CleanedName)); diff --git a/Plugins/Mute/Mute.csproj b/Plugins/Mute/Mute.csproj index b945045f9..69cbfdcf5 100644 --- a/Plugins/Mute/Mute.csproj +++ b/Plugins/Mute/Mute.csproj @@ -11,7 +11,7 @@ - + diff --git a/Plugins/Mute/MuteManager.cs b/Plugins/Mute/MuteManager.cs index d9239aa03..5f91d8169 100644 --- a/Plugins/Mute/MuteManager.cs +++ b/Plugins/Mute/MuteManager.cs @@ -1,7 +1,6 @@ using Data.Abstractions; using Data.Models; using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using SharedLibraryCore; using SharedLibraryCore.Database.Models; @@ -9,7 +8,7 @@ using SharedLibraryCore.Interfaces; using static System.Enum; using ILogger = Microsoft.Extensions.Logging.ILogger; -namespace Mute; +namespace IW4MAdmin.Plugins.Mute; public class MuteManager { @@ -19,12 +18,13 @@ public class MuteManager private readonly IDatabaseContextFactory _databaseContextFactory; private readonly SemaphoreSlim _onMuteAction = new(1, 1); - public MuteManager(IServiceProvider serviceProvider) + public MuteManager(ILogger logger, IDatabaseContextFactory databaseContextFactory, + IMetaServiceV2 metaService, ITranslationLookup translationLookup) { - _metaService = serviceProvider.GetRequiredService(); - _translationLookup = serviceProvider.GetRequiredService(); - _logger = serviceProvider.GetRequiredService>(); - _databaseContextFactory = serviceProvider.GetRequiredService(); + _logger = logger; + _databaseContextFactory = databaseContextFactory; + _metaService = metaService; + _translationLookup = translationLookup; } public static bool IsExpiredMute(MuteStateMeta muteStateMeta) => diff --git a/Plugins/Mute/MuteStateMeta.cs b/Plugins/Mute/MuteStateMeta.cs index d37fb81f9..85d745732 100644 --- a/Plugins/Mute/MuteStateMeta.cs +++ b/Plugins/Mute/MuteStateMeta.cs @@ -1,6 +1,6 @@ using System.Text.Json.Serialization; -namespace Mute; +namespace IW4MAdmin.Plugins.Mute; public class MuteStateMeta { diff --git a/Plugins/Mute/Plugin.cs b/Plugins/Mute/Plugin.cs index 6df57b0e6..f2b0e2c54 100644 --- a/Plugins/Mute/Plugin.cs +++ b/Plugins/Mute/Plugin.cs @@ -1,119 +1,54 @@ -using Data.Abstractions; -using Microsoft.Extensions.Logging; -using Mute.Commands; +using IW4MAdmin.Plugins.Mute.Commands; +using Microsoft.Extensions.DependencyInjection; using SharedLibraryCore; using SharedLibraryCore.Commands; using SharedLibraryCore.Database.Models; +using SharedLibraryCore.Events.Game; +using SharedLibraryCore.Events.Management; +using SharedLibraryCore.Events.Server; using SharedLibraryCore.Helpers; using SharedLibraryCore.Interfaces; +using SharedLibraryCore.Interfaces.Events; using JsonSerializer = System.Text.Json.JsonSerializer; -namespace Mute; +namespace IW4MAdmin.Plugins.Mute; -public class Plugin : IPlugin +public class Plugin : IPluginV2 { public string Name => "Mute"; - public float Version => (float)Utilities.GetVersionAsDouble(); + public string Version => Utilities.GetVersionAsString(); public string Author => "Amos"; public const string MuteKey = "IW4MMute"; - public static MuteManager MuteManager { get; private set; } = null!; public static IManager Manager { get; private set; } = null!; public static readonly Server.Game[] SupportedGames = {Server.Game.IW4}; private static readonly string[] DisabledCommands = {nameof(PrivateMessageAdminsCommand), "PrivateMessageCommand"}; private readonly IInteractionRegistration _interactionRegistration; private readonly IRemoteCommandService _remoteCommandService; - private static readonly string MuteInteraction = "Webfront::Profile::Mute"; + private readonly MuteManager _muteManager; + private const string MuteInteraction = "Webfront::Profile::Mute"; - public Plugin(ILogger logger, IInteractionRegistration interactionRegistration, - IRemoteCommandService remoteCommandService, IServiceProvider serviceProvider) + public Plugin(IInteractionRegistration interactionRegistration, + IRemoteCommandService remoteCommandService, MuteManager muteManager) { _interactionRegistration = interactionRegistration; _remoteCommandService = remoteCommandService; - MuteManager = new MuteManager(serviceProvider); + _muteManager = muteManager; + + IManagementEventSubscriptions.Load += OnLoad; + IManagementEventSubscriptions.Unload += OnUnload; + + IManagementEventSubscriptions.ClientStateInitialized += OnClientStateInitialized; + IGameServerEventSubscriptions.ClientDataUpdated += OnClientDataUpdated; + IGameEventSubscriptions.ClientMessaged += OnClientMessaged; } - public async Task OnEventAsync(GameEvent gameEvent, Server server) + public static void RegisterDependencies(IServiceCollection serviceProvider) { - if (!SupportedGames.Contains(server.GameName)) return; - - switch (gameEvent.Type) - { - case GameEvent.EventType.Join: - // Check if user has any meta set, else ignore (unmuted) - var muteMetaJoin = await MuteManager.GetCurrentMuteState(gameEvent.Origin); - - switch (muteMetaJoin.MuteState) - { - case MuteState.Muted: - // Let the client know when their mute expires. - gameEvent.Origin.Tell(Utilities.CurrentLocalization - .LocalizationIndex["PLUGINS_MUTE_REMAINING_TIME"].FormatExt( - muteMetaJoin.Expiration is not null - ? muteMetaJoin.Expiration.Value.HumanizeForCurrentCulture() - : Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_MUTE_NEVER"], - muteMetaJoin.Reason)); - break; - case MuteState.Unmuting: - // Handle unmute of unmuted players. - await MuteManager.Unmute(server, Utilities.IW4MAdminClient(), gameEvent.Origin, - muteMetaJoin.Reason ?? string.Empty); - gameEvent.Origin.Tell(Utilities.CurrentLocalization - .LocalizationIndex["PLUGINS_MUTE_COMMANDS_UNMUTE_TARGET_UNMUTED"] - .FormatExt(muteMetaJoin.Reason)); - break; - } - - break; - case GameEvent.EventType.Say: - var muteMetaSay = await MuteManager.GetCurrentMuteState(gameEvent.Origin); - - switch (muteMetaSay.MuteState) - { - case MuteState.Muted: - // Let the client know when their mute expires. - gameEvent.Origin.Tell(Utilities.CurrentLocalization - .LocalizationIndex["PLUGINS_MUTE_REMAINING_TIME"].FormatExt( - muteMetaSay.Expiration is not null - ? muteMetaSay.Expiration.Value.HumanizeForCurrentCulture() - : Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_MUTE_NEVER"], - muteMetaSay.Reason)); - break; - } - - break; - case GameEvent.EventType.Update: - // Get correct EFClient object - var client = server.GetClientsAsList() - .FirstOrDefault(client => client.NetworkId == gameEvent.Origin.NetworkId); - if (client == null) break; - - var muteMetaUpdate = await MuteManager.GetCurrentMuteState(client); - if (!muteMetaUpdate.CommandExecuted) - { - await MuteManager.PerformGameCommand(server, client, muteMetaUpdate); - } - - switch (muteMetaUpdate.MuteState) - { - case MuteState.Muted: - // Handle unmute if expired. - if (MuteManager.IsExpiredMute(muteMetaUpdate)) - { - await MuteManager.Unmute(server, Utilities.IW4MAdminClient(), client, - Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_MUTE_EXPIRED"]); - client.Tell( - Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_MUTE_TARGET_EXPIRED"]); - } - - break; - } - - break; - } + serviceProvider.AddSingleton(); } - public Task OnLoadAsync(IManager manager) + private Task OnLoad(IManager manager, CancellationToken cancellationToken) { Manager = manager; @@ -124,7 +59,7 @@ public class Plugin : IPlugin return true; } - var muteMeta = MuteManager.GetCurrentMuteState(gameEvent.Origin).GetAwaiter().GetResult(); + var muteMeta = _muteManager.GetCurrentMuteState(gameEvent.Origin).GetAwaiter().GetResult(); if (muteMeta.MuteState is not MuteState.Muted) { return true; @@ -141,7 +76,7 @@ public class Plugin : IPlugin } var clientMuteMetaState = - (await MuteManager.GetCurrentMuteState(new EFClient {ClientId = targetClientId.Value})) + (await _muteManager.GetCurrentMuteState(new EFClient {ClientId = targetClientId.Value})) .MuteState; var server = manager.GetServers().First(); @@ -154,6 +89,91 @@ public class Plugin : IPlugin }); return Task.CompletedTask; } + + private Task OnUnload(IManager manager, CancellationToken token) + { + _interactionRegistration.UnregisterInteraction(MuteInteraction); + return Task.CompletedTask; + } + + private async Task OnClientDataUpdated(ClientDataUpdateEvent updateEvent, CancellationToken token) + { + if (!updateEvent.Server.ConnectedClients.Any()) + { + return; + } + + var networkIds = updateEvent.Clients.Select(client => client.NetworkId).ToList(); + var ingameClients = updateEvent.Server.ConnectedClients.Where(client => networkIds.Contains(client.NetworkId)); + + await Task.WhenAll(ingameClients.Select(async client => + { + var muteMetaUpdate = await _muteManager.GetCurrentMuteState(client); + if (!muteMetaUpdate.CommandExecuted) + { + await MuteManager.PerformGameCommand(client.CurrentServer, client, muteMetaUpdate); + } + + if (muteMetaUpdate.MuteState == MuteState.Muted) + { + // Handle unmute if expired. + if (MuteManager.IsExpiredMute(muteMetaUpdate)) + { + await _muteManager.Unmute(client.CurrentServer, Utilities.IW4MAdminClient(), client, + Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_MUTE_EXPIRED"]); + client.Tell( + Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_MUTE_TARGET_EXPIRED"]); + } + } + })); + } + + private async Task OnClientMessaged(ClientMessageEvent messageEvent, CancellationToken token) + { + var muteMetaSay = await _muteManager.GetCurrentMuteState(messageEvent.Origin); + + if (muteMetaSay.MuteState == MuteState.Muted) + { + // Let the client know when their mute expires. + messageEvent.Origin.Tell(Utilities.CurrentLocalization + .LocalizationIndex["PLUGINS_MUTE_REMAINING_TIME"].FormatExt( + muteMetaSay.Expiration is not null + ? muteMetaSay.Expiration.Value.HumanizeForCurrentCulture() + : Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_MUTE_NEVER"], + muteMetaSay.Reason)); + } + } + + private async Task OnClientStateInitialized(ClientStateInitializeEvent state, CancellationToken token) + { + if (!SupportedGames.Contains(state.Client.CurrentServer.GameName)) + { + return; + } + + var muteMetaJoin = await _muteManager.GetCurrentMuteState(state.Client); + + switch (muteMetaJoin) + { + case { MuteState: MuteState.Muted }: + // Let the client know when their mute expires. + state.Client.Tell(Utilities.CurrentLocalization + .LocalizationIndex["PLUGINS_MUTE_REMAINING_TIME"].FormatExt( + muteMetaJoin is { Expiration: not null } + ? muteMetaJoin.Expiration.Value.HumanizeForCurrentCulture() + : Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_MUTE_NEVER"], + muteMetaJoin.Reason)); + break; + case { MuteState: MuteState.Unmuting }: + // Handle unmute of unmuted players. + await _muteManager.Unmute(state.Client.CurrentServer, Utilities.IW4MAdminClient(), state.Client, + muteMetaJoin.Reason ?? string.Empty); + state.Client.Tell(Utilities.CurrentLocalization + .LocalizationIndex["PLUGINS_MUTE_COMMANDS_UNMUTE_TARGET_UNMUTED"] + .FormatExt(muteMetaJoin.Reason)); + break; + } + } private InteractionData CreateMuteInteraction(int targetClientId, Server server, Func getCommandNameFunc) @@ -297,15 +317,4 @@ public class Plugin : IPlugin } }; } - - public Task OnUnloadAsync() - { - _interactionRegistration.UnregisterInteraction(MuteInteraction); - return Task.CompletedTask; - } - - public Task OnTickAsync(Server server) - { - return Task.CompletedTask; - } }