From 3ae2e427189ad87ed1e85250233d24a5714053e5 Mon Sep 17 00:00:00 2001 From: RaidMax Date: Mon, 20 Apr 2020 10:45:58 -0500 Subject: [PATCH] properly implement sv_sayName for custom say name prevent trying to register live radar page for every server (oops) optimize event processing to prevent slow plugins from affecting command processing enable database connection resilency trim extra characters from T7 reassembled response --- Application/GameEventHandler.cs | 15 +++--- Application/IW4MServer.cs | 54 ++++++++++++------- Application/RCon/RConConnection.cs | 2 +- Plugins/LiveRadar/Plugin.cs | 7 ++- SharedLibraryCore/Database/DatabaseContext.cs | 4 +- SharedLibraryCore/Events/GameEvent.cs | 4 +- SharedLibraryCore/Server.cs | 2 +- 7 files changed, 55 insertions(+), 33 deletions(-) diff --git a/Application/GameEventHandler.cs b/Application/GameEventHandler.cs index ba9d75217..b370e883b 100644 --- a/Application/GameEventHandler.cs +++ b/Application/GameEventHandler.cs @@ -5,6 +5,7 @@ using SharedLibraryCore.Interfaces; using System; using System.Linq; using System.Threading; +using System.Threading.Tasks; namespace IW4MAdmin.Application { @@ -12,9 +13,6 @@ namespace IW4MAdmin.Application { readonly ApplicationManager Manager; private readonly EventProfiler _profiler; - private delegate void GameEventAddedEventHandler(object sender, GameEventArgs args); - private event GameEventAddedEventHandler GameEventAdded; - private static readonly GameEvent.EventType[] overrideEvents = new[] { GameEvent.EventType.Connect, @@ -27,14 +25,16 @@ namespace IW4MAdmin.Application { Manager = (ApplicationManager)mgr; _profiler = new EventProfiler(mgr.GetLogger(0)); - GameEventAdded += GameEventHandler_GameEventAdded; } - private async void GameEventHandler_GameEventAdded(object sender, GameEventArgs args) + private Task GameEventHandler_GameEventAdded(object sender, GameEventArgs args) { +#if DEBUG var start = DateTime.Now; - await Manager.ExecuteEvent(args.Event); +#endif EventApi.OnGameEvent(sender, args); + return Manager.ExecuteEvent(args.Event); + #if DEBUG _profiler.Profile(start, DateTime.Now, args.Event); #endif @@ -53,7 +53,8 @@ namespace IW4MAdmin.Application #if DEBUG gameEvent.Owner.Logger.WriteDebug($"Adding event with id {gameEvent.Id}"); #endif - GameEventAdded?.Invoke(this, new GameEventArgs(null, false, gameEvent)); + //GameEventAdded?.Invoke(this, new GameEventArgs(null, false, gameEvent)); + Task.Run(() => GameEventHandler_GameEventAdded(this, new GameEventArgs(null, false, gameEvent))); } #if DEBUG else diff --git a/Application/IW4MServer.cs b/Application/IW4MServer.cs index 0cca3c739..498679fba 100644 --- a/Application/IW4MServer.cs +++ b/Application/IW4MServer.cs @@ -152,36 +152,49 @@ namespace IW4MAdmin } } - foreach (var plugin in Manager.Plugins) + try { - try - { - // we don't want to run the events on parser plugins - if (plugin is ScriptPlugin scriptPlugin && scriptPlugin.IsParser) - { - continue; - } + var loginPlugin = Manager.Plugins.FirstOrDefault(_plugin => _plugin.Name == "Login"); - await plugin.OnEventAsync(E, this); - } - catch (AuthorizationException e) + if (loginPlugin != null) { - E.Origin.Tell($"{loc["COMMAND_NOTAUTHORIZED"]} - {e.Message}"); - canExecuteCommand = false; - } - catch (Exception Except) - { - Logger.WriteError($"{loc["SERVER_PLUGIN_ERROR"]} [{plugin.Name}]"); - Logger.WriteDebug(Except.GetExceptionInfo()); + await loginPlugin.OnEventAsync(E, this); } } + catch (AuthorizationException e) + { + E.Origin.Tell($"{loc["COMMAND_NOTAUTHORIZED"]} - {e.Message}"); + canExecuteCommand = false; + } + // hack: this prevents commands from getting executing that 'shouldn't' be if (E.Type == GameEvent.EventType.Command && E.Extra is Command command && (canExecuteCommand || E.Origin?.Level == Permission.Console)) { await command.ExecuteAsync(E); } + + var pluginTasks = Manager.Plugins.Where(_plugin => _plugin.Name != "Login").Select(async _plugin => + { + try + { + // we don't want to run the events on parser plugins + if (_plugin is ScriptPlugin scriptPlugin && scriptPlugin.IsParser) + { + return; + } + + await _plugin.OnEventAsync(E, this); + } + catch (Exception Except) + { + Logger.WriteError($"{loc["SERVER_PLUGIN_ERROR"]} [{_plugin.Name}]"); + Logger.WriteDebug(Except.GetExceptionInfo()); + } + }); + + Parallel.ForEach(pluginTasks, async (_task) => await _task); } catch (Exception e) @@ -944,6 +957,11 @@ namespace IW4MAdmin var logsync = await this.GetDvarAsync("g_logsync"); var ip = await this.GetDvarAsync("net_ip"); + if (Manager.GetApplicationSettings().Configuration().EnableCustomSayName) + { + await this.SetDvarAsync("sv_sayname", Manager.GetApplicationSettings().Configuration().CustomSayName); + } + try { var website = await this.GetDvarAsync("_website"); diff --git a/Application/RCon/RConConnection.cs b/Application/RCon/RConConnection.cs index 9e9634b79..3ced4b19a 100644 --- a/Application/RCon/RConConnection.cs +++ b/Application/RCon/RConConnection.cs @@ -220,7 +220,7 @@ namespace IW4MAdmin.Application.RCon var statusHeaderMatch = config.StatusHeader.PatternMatcher.Match(responseString); if (statusHeaderMatch.Success) { - splitStatusStrings.Insert(0, responseString); + splitStatusStrings.Insert(0, responseString.TrimEnd('\0')); } else diff --git a/Plugins/LiveRadar/Plugin.cs b/Plugins/LiveRadar/Plugin.cs index 8558713fe..20cd22466 100644 --- a/Plugins/LiveRadar/Plugin.cs +++ b/Plugins/LiveRadar/Plugin.cs @@ -17,6 +17,7 @@ namespace LiveRadar public string Author => "RaidMax"; private readonly IConfigurationHandler _configurationHandler; + private bool addedPage; public Plugin(IConfigurationHandlerFactory configurationHandlerFactory) { @@ -27,11 +28,13 @@ namespace LiveRadar { // if it's an IW4 game, with custom callbacks, we want to // enable the live radar page - if (E.Type == GameEvent.EventType.Start && + if (E.Type == GameEvent.EventType.Start && S.GameName == Server.Game.IW4 && - S.CustomCallback) + S.CustomCallback && + !addedPage) { E.Owner.Manager.GetPageList().Pages.Add(Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_RADAR_TITLE"], "/Radar/All"); + addedPage = true; } if (E.Type == GameEvent.EventType.Unknown) diff --git a/SharedLibraryCore/Database/DatabaseContext.cs b/SharedLibraryCore/Database/DatabaseContext.cs index c0201dff8..2e158526d 100644 --- a/SharedLibraryCore/Database/DatabaseContext.cs +++ b/SharedLibraryCore/Database/DatabaseContext.cs @@ -95,10 +95,10 @@ namespace SharedLibraryCore.Database { default: case "mysql": - optionsBuilder.UseMySql(_ConnectionString); + optionsBuilder.UseMySql(_ConnectionString, _options => _options.EnableRetryOnFailure()); break; case "postgresql": - optionsBuilder.UseNpgsql(_ConnectionString); + optionsBuilder.UseNpgsql(_ConnectionString, _options => _options.EnableRetryOnFailure()); break; } } diff --git a/SharedLibraryCore/Events/GameEvent.cs b/SharedLibraryCore/Events/GameEvent.cs index 3298d085a..9d78585f9 100644 --- a/SharedLibraryCore/Events/GameEvent.cs +++ b/SharedLibraryCore/Events/GameEvent.cs @@ -273,11 +273,11 @@ namespace SharedLibraryCore if (!processed) { + Owner?.Logger.WriteError("Waiting for event to complete timed out"); + Owner?.Logger.WriteDebug($"{Id}, {Type}, {Data}, {Extra}, {FailReason.ToString()}, {Message}, {Origin}, {Target}"); #if DEBUG throw new Exception(); #endif - Owner?.Logger.WriteError("Waiting for event to complete timed out"); - Owner?.Logger.WriteDebug($"{Id}, {Type}, {Data}, {Extra}, {FailReason.ToString()}, {Message}, {Origin}, {Target}"); } diff --git a/SharedLibraryCore/Server.cs b/SharedLibraryCore/Server.cs index 0807eb191..2ca24a086 100644 --- a/SharedLibraryCore/Server.cs +++ b/SharedLibraryCore/Server.cs @@ -147,7 +147,7 @@ namespace SharedLibraryCore protected async Task Tell(string message, EFClient target) { #if !DEBUG - string formattedMessage = string.Format(RconParser.Configuration.CommandPrefixes.Tell, target.ClientNumber, $"{(CustomSayEnabled ? $"{CustomSayName}: " : "")}{message.FixIW4ForwardSlash()}"); + string formattedMessage = string.Format(RconParser.Configuration.CommandPrefixes.Tell, target.ClientNumber, $"{(CustomSayEnabled && GameName == Game.IW4 ? $"{CustomSayName}: " : "")}{message.FixIW4ForwardSlash()}"); if (target.ClientNumber > -1 && message.Length > 0 && target.Level != EFClient.Permission.Console) await this.ExecuteCommandAsync(formattedMessage); #else