diff --git a/GameFiles/GameInterface/_integration_iw5.gsc b/GameFiles/GameInterface/_integration_iw5.gsc
index fd4d652a..6dfc6a7c 100644
--- a/GameFiles/GameInterface/_integration_iw5.gsc
+++ b/GameFiles/GameInterface/_integration_iw5.gsc
@@ -193,7 +193,7 @@ NoClipImpl()
self God();
self Noclip();
- self Hide();
+ self Show();
SetDvar( "sv_cheats", 0 );
diff --git a/Plugins/Mute/Mute.csproj b/Plugins/Mute/Mute.csproj
index a89ad5ba..460888bd 100644
--- a/Plugins/Mute/Mute.csproj
+++ b/Plugins/Mute/Mute.csproj
@@ -8,6 +8,7 @@
Library
Debug;Release;Prerelease
AnyCPU
+ IW4MAdmin.Plugins.Mute
diff --git a/Plugins/Mute/MuteManager.cs b/Plugins/Mute/MuteManager.cs
index 5f91d816..537465b1 100644
--- a/Plugins/Mute/MuteManager.cs
+++ b/Plugins/Mute/MuteManager.cs
@@ -131,8 +131,11 @@ public class MuteManager
{
var newPenalty = new EFPenalty
{
- Type = muteState is MuteState.Unmuted ? EFPenalty.PenaltyType.Unmute :
- dateTime is null ? EFPenalty.PenaltyType.Mute : EFPenalty.PenaltyType.TempMute,
+ Type = muteState is MuteState.Unmuted
+ ? EFPenalty.PenaltyType.Unmute
+ : dateTime is null
+ ? EFPenalty.PenaltyType.Mute
+ : EFPenalty.PenaltyType.TempMute,
Expires = muteState is MuteState.Unmuted ? DateTime.UtcNow : dateTime,
Offender = target,
Offense = reason,
@@ -148,10 +151,9 @@ public class MuteManager
{
await using var context = _databaseContextFactory.CreateContext();
var mutePenalties = await context.Penalties
- .Where(penalty => penalty.OffenderId == client.ClientId &&
- (penalty.Type == EFPenalty.PenaltyType.Mute ||
- penalty.Type == EFPenalty.PenaltyType.TempMute) &&
- (penalty.Expires == null || penalty.Expires > DateTime.UtcNow))
+ .Where(penalty => penalty.OffenderId == client.ClientId)
+ .Where(penalty => penalty.Type == EFPenalty.PenaltyType.Mute || penalty.Type == EFPenalty.PenaltyType.TempMute)
+ .Where(penalty => penalty.Expires == null || penalty.Expires > DateTime.UtcNow)
.ToListAsync();
foreach (var mutePenalty in mutePenalties)
@@ -169,19 +171,20 @@ public class MuteManager
switch (muteStateMeta.MuteState)
{
case MuteState.Muted:
- await server.ExecuteCommandAsync($"muteClient {client.ClientNumber}");
+ var muteCommand = string.Format(server.RconParser.Configuration.CommandPrefixes.Mute, client.ClientNumber);
+ await server.ExecuteCommandAsync(muteCommand);
muteStateMeta.CommandExecuted = true;
break;
case MuteState.Unmuted:
- await server.ExecuteCommandAsync($"unmute {client.ClientNumber}");
+ var unMuteCommand = string.Format(server.RconParser.Configuration.CommandPrefixes.Unmute, client.ClientNumber);
+ await server.ExecuteCommandAsync(unMuteCommand);
muteStateMeta.CommandExecuted = true;
break;
}
}
private async Task ReadPersistentDataV1(EFClient client) => TryParse(
- (await _metaService.GetPersistentMeta(Plugin.MuteKey, client.ClientId))?.Value,
- out var muteState)
+ (await _metaService.GetPersistentMeta(Plugin.MuteKey, client.ClientId))?.Value, out var muteState)
? muteState
: null;
diff --git a/Plugins/Mute/Plugin.cs b/Plugins/Mute/Plugin.cs
index 242857da..fc75ea27 100644
--- a/Plugins/Mute/Plugin.cs
+++ b/Plugins/Mute/Plugin.cs
@@ -21,7 +21,7 @@ public class Plugin : IPluginV2
public const string MuteKey = "IW4MMute";
public static IManager Manager { get; private set; } = null!;
- public static readonly Server.Game[] SupportedGames = {Server.Game.IW4};
+ public static Server.Game[] SupportedGames { get; private set; } = Array.Empty();
private static readonly string[] DisabledCommands = {nameof(PrivateMessageAdminsCommand), "PrivateMessageCommand"};
private readonly IInteractionRegistration _interactionRegistration;
private readonly IRemoteCommandService _remoteCommandService;
@@ -34,12 +34,14 @@ public class Plugin : IPluginV2
_interactionRegistration = interactionRegistration;
_remoteCommandService = remoteCommandService;
_muteManager = muteManager;
-
+
IManagementEventSubscriptions.Load += OnLoad;
IManagementEventSubscriptions.Unload += OnUnload;
-
IManagementEventSubscriptions.ClientStateInitialized += OnClientStateInitialized;
+
IGameServerEventSubscriptions.ClientDataUpdated += OnClientDataUpdated;
+ IGameServerEventSubscriptions.MonitoringStarted += OnServerMonitoredStarted;
+
IGameEventSubscriptions.ClientMessaged += OnClientMessaged;
}
@@ -61,7 +63,7 @@ public class Plugin : IPluginV2
var muteMeta = Task.Run(() => _muteManager.GetCurrentMuteState(gameEvent.Origin), cancellationToken)
.GetAwaiter().GetResult();
-
+
if (muteMeta.MuteState is not MuteState.Muted)
{
return true;
@@ -91,7 +93,7 @@ public class Plugin : IPluginV2
});
return Task.CompletedTask;
}
-
+
private Task OnUnload(IManager manager, CancellationToken token)
{
_interactionRegistration.UnregisterInteraction(MuteInteraction);
@@ -152,21 +154,21 @@ public class Plugin : IPluginV2
{
return;
}
-
+
var muteMetaJoin = await _muteManager.GetCurrentMuteState(state.Client);
switch (muteMetaJoin)
{
- case { MuteState: MuteState.Muted }:
+ 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 is {Expiration: not null}
? muteMetaJoin.Expiration.Value.HumanizeForCurrentCulture()
: Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_MUTE_NEVER"],
muteMetaJoin.Reason));
break;
- case { MuteState: MuteState.Unmuting }:
+ case {MuteState: MuteState.Unmuting}:
// Handle unmute of unmuted players.
await _muteManager.Unmute(state.Client.CurrentServer, Utilities.IW4MAdminClient(), state.Client,
muteMetaJoin.Reason ?? string.Empty);
@@ -319,4 +321,29 @@ public class Plugin : IPluginV2
}
};
}
+
+ private Task OnServerMonitoredStarted(MonitorStartEvent serverEvent, CancellationToken token)
+ {
+ var game = (Server.Game)serverEvent.Server.GameCode;
+
+ lock (SupportedGames)
+ {
+ if (SupportedGames.Contains(game))
+ {
+ return Task.CompletedTask;
+ }
+
+ var server = Manager.GetServers().FirstOrDefault(x => x == serverEvent.Server);
+ var commandIsEmpty = string.IsNullOrWhiteSpace(server?.RconParser.Configuration.CommandPrefixes.Mute);
+
+ if (commandIsEmpty)
+ {
+ return Task.CompletedTask;
+ }
+
+ SupportedGames = SupportedGames.Append(game).ToArray();
+ }
+
+ return Task.CompletedTask;
+ }
}
diff --git a/Plugins/ScriptPlugins/ParserIW4x.js b/Plugins/ScriptPlugins/ParserIW4x.js
index b35ef0d0..0d9cf3a2 100644
--- a/Plugins/ScriptPlugins/ParserIW4x.js
+++ b/Plugins/ScriptPlugins/ParserIW4x.js
@@ -19,6 +19,8 @@ var plugin = {
rconParser.Configuration.CommandPrefixes.Kick = 'clientkick {0} "{1}"';
rconParser.Configuration.CommandPrefixes.Ban = 'clientkick {0} "{1}"';
rconParser.Configuration.CommandPrefixes.TempBan = 'tempbanclient {0} "{1}"';
+ rconParser.Configuration.CommandPrefixes.Mute = 'muteClient {0}';
+ rconParser.Configuration.CommandPrefixes.Unmute = 'unmute {0}';
rconParser.Configuration.DefaultRConPort = 28960;
rconParser.Configuration.DefaultInstallationDirectoryHint = 'HKEY_CURRENT_USER\\Software\\Classes\\iw4x\\shell\\open\\command';
diff --git a/Plugins/ScriptPlugins/ParserIW6x.js b/Plugins/ScriptPlugins/ParserIW6x.js
index 7c399aa8..4185bb35 100644
--- a/Plugins/ScriptPlugins/ParserIW6x.js
+++ b/Plugins/ScriptPlugins/ParserIW6x.js
@@ -20,6 +20,8 @@ var plugin = {
rconParser.Configuration.CommandPrefixes.Ban = 'clientkick {0} "{1}"';
rconParser.Configuration.CommandPrefixes.TempBan = 'clientkick {0} "{1}"';
rconParser.Configuration.CommandPrefixes.RConResponse = '\xff\xff\xff\xffprint\n';
+ rconParser.Configuration.CommandPrefixes.Mute = 'muteClient {0}';
+ rconParser.Configuration.CommandPrefixes.Unmute = 'unmuteClient {0}';
rconParser.Configuration.Dvar.Pattern = '^ *\\"(.+)\\" is: \\"(.+)?\\" default: \\"(.+)?\\"\\n?(?:latched: \\"(.+)?\\"\\n?)?(.*)$';
rconParser.Configuration.Status.Pattern = '^ *([0-9]+) +-?([0-9]+) +(Yes|No) +((?:[A-Z]+|[0-9]+)) +((?:[a-z]|[0-9]){8,32}|(?:[a-z]|[0-9]){8,32}|bot[0-9]+|(?:[0-9]+)) *(.{0,32}) +(\\d+\\.\\d+\\.\\d+.\\d+\\:-*\\d{1,5}|0+.0+:-*\\d{1,5}|loopback|unknown|bot) +(-*[0-9]+) *$';
rconParser.Configuration.StatusHeader.Pattern = 'num +score +bot +ping +guid +name +address +qport *';