diff --git a/Application/Application.csproj b/Application/Application.csproj
index 9abb26c6..0f73533c 100644
--- a/Application/Application.csproj
+++ b/Application/Application.csproj
@@ -5,7 +5,7 @@
netcoreapp3.1
false
RaidMax.IW4MAdmin.Application
- 2.3.1.0
+ 2.3.2.0
RaidMax
Forever None
IW4MAdmin
diff --git a/Application/ApplicationManager.cs b/Application/ApplicationManager.cs
index e0b390af..efe53f30 100644
--- a/Application/ApplicationManager.cs
+++ b/Application/ApplicationManager.cs
@@ -256,9 +256,25 @@ namespace IW4MAdmin.Application
if (plugin is ScriptPlugin scriptPlugin)
{
await scriptPlugin.Initialize(this);
+ scriptPlugin.Watcher.Changed += async (sender, e) =>
+ {
+ try
+ {
+ await scriptPlugin.Initialize(this);
+ }
+
+ catch (Exception ex)
+ {
+ Logger.WriteError(Utilities.CurrentLocalization.LocalizationIndex["PLUGIN_IMPORTER_ERROR"].FormatExt(scriptPlugin.Name));
+ Logger.WriteDebug(ex.Message);
+ }
+ };
}
- await plugin.OnLoadAsync(this);
+ else
+ {
+ await plugin.OnLoadAsync(this);
+ }
}
catch (Exception ex)
diff --git a/Application/IW4MServer.cs b/Application/IW4MServer.cs
index 0f2f3f28..6afdb110 100644
--- a/Application/IW4MServer.cs
+++ b/Application/IW4MServer.cs
@@ -881,9 +881,9 @@ namespace IW4MAdmin
Version = RconParser.Version;
}
- var svRunning = await this.GetDvarAsync("sv_running");
+ var svRunning = await this.GetDvarAsync("sv_running");
- if (svRunning.Value == 0)
+ if (!string.IsNullOrEmpty(svRunning.Value) && svRunning.Value != "1")
{
throw new ServerException(loc["SERVER_ERROR_NOT_RUNNING"]);
}
diff --git a/Application/Main.cs b/Application/Main.cs
index 9eea2d7d..f49ea19a 100644
--- a/Application/Main.cs
+++ b/Application/Main.cs
@@ -8,6 +8,7 @@ using SharedLibraryCore.Exceptions;
using SharedLibraryCore.Helpers;
using SharedLibraryCore.Interfaces;
using System;
+using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
@@ -68,30 +69,9 @@ namespace IW4MAdmin.Application
try
{
var services = ConfigureServices();
-
- using (var builder = services.BuildServiceProvider())
- {
- translationLookup = builder.GetRequiredService();
- var importer = builder.GetRequiredService();
- importer.Load();
-
- foreach (var type in importer.CommandTypes)
- {
- services.AddTransient(typeof(IManagerCommand), type);
- }
-
- foreach (var commandDefinition in typeof(SharedLibraryCore.Commands.QuitCommand).Assembly.GetTypes()
- .Where(_command => _command.BaseType == typeof(Command)))
- {
- services.AddTransient(typeof(IManagerCommand), commandDefinition);
- }
- }
-
serviceProvider = services.BuildServiceProvider();
- var pluginImporter = serviceProvider.GetRequiredService();
- pluginImporter.Load();
-
ServerManager = (ApplicationManager)serviceProvider.GetRequiredService();
+ translationLookup = serviceProvider.GetRequiredService();
// do any needed housekeeping file/folder migrations
ConfigurationMigration.MoveConfigFolder10518(null);
@@ -283,8 +263,8 @@ namespace IW4MAdmin.Application
///
private static IServiceCollection ConfigureServices()
{
- var serviceProvider = new ServiceCollection();
- serviceProvider.AddSingleton()
+ var serviceCollection = new ServiceCollection();
+ serviceCollection.AddSingleton(_serviceProvider => serviceCollection)
.AddSingleton(new BaseConfigurationHandler("IW4MAdminSettings") as IConfigurationHandler)
.AddSingleton(new BaseConfigurationHandler("CommandConfiguration") as IConfigurationHandler)
.AddSingleton(_serviceProvider => _serviceProvider.GetRequiredService>().Configuration())
@@ -292,14 +272,27 @@ namespace IW4MAdmin.Application
.AddSingleton(_serviceProvider => new Logger("IW4MAdmin-Manager"))
.AddSingleton()
.AddSingleton()
+ .AddTransient(_serviceProvider =>
+ {
+ var importer = _serviceProvider.GetRequiredService();
+ var config = _serviceProvider.GetRequiredService();
+ var layout = _serviceProvider.GetRequiredService();
+
+ // todo: this is disgusting, but I need it until I can figure out a way to dynamically load the plugins without creating an instance.
+ return importer.CommandTypes.
+ Union(typeof(SharedLibraryCore.Commands.QuitCommand).Assembly.GetTypes()
+ .Where(_command => _command.BaseType == typeof(Command)))
+ .Select(_cmdType => Activator.CreateInstance(_cmdType, config, layout) as IManagerCommand);
+ })
.AddSingleton(_serviceProvider =>
{
var config = _serviceProvider.GetRequiredService>().Configuration();
return Localization.Configure.Initialize(useLocalTranslation: config?.UseLocalTranslations ?? false,
customLocale: config?.EnableCustomLocale ?? false ? (config.CustomLocale ?? "en-US") : "en-US");
- });
+ })
+ .AddSingleton();
- return serviceProvider;
+ return serviceCollection;
}
}
}
diff --git a/Application/Misc/PluginImporter.cs b/Application/Misc/PluginImporter.cs
index 3231ad7d..cb6c73e1 100644
--- a/Application/Misc/PluginImporter.cs
+++ b/Application/Misc/PluginImporter.cs
@@ -22,12 +22,14 @@ namespace IW4MAdmin.Application.Helpers
{
_logger = logger;
_translationLookup = translationLookup;
+
+ Load();
}
///
/// Loads all the assembly and javascript plugins
///
- public void Load()
+ private void Load()
{
string pluginDir = $"{Utilities.OperatingDirectory}Plugins{Path.DirectorySeparatorChar}";
string[] dllFileNames = null;
diff --git a/SharedLibraryCore/Commands/NativeCommands.cs b/SharedLibraryCore/Commands/NativeCommands.cs
index 2cf2d717..09da50e6 100644
--- a/SharedLibraryCore/Commands/NativeCommands.cs
+++ b/SharedLibraryCore/Commands/NativeCommands.cs
@@ -1315,7 +1315,7 @@ namespace SharedLibraryCore.Commands
///
/// Lists the loaded plugins
///
- public class ListPluginsCommand : Command
+ /*public class ListPluginsCommand : Command
{
private readonly IPluginImporter _pluginImporter;
public ListPluginsCommand(CommandConfiguration config, ITranslationLookup translationLookup, IPluginImporter pluginImporter) : base(config, translationLookup)
@@ -1337,7 +1337,7 @@ namespace SharedLibraryCore.Commands
}
return Task.CompletedTask;
}
- }
+ }*/
///
/// Lists external IP
diff --git a/SharedLibraryCore/Interfaces/IPluginImporter.cs b/SharedLibraryCore/Interfaces/IPluginImporter.cs
index 0e7d45ad..7403ce14 100644
--- a/SharedLibraryCore/Interfaces/IPluginImporter.cs
+++ b/SharedLibraryCore/Interfaces/IPluginImporter.cs
@@ -28,10 +28,5 @@ namespace SharedLibraryCore.Interfaces
/// All assemblies in the plugin folder
///
IList Assemblies { get; }
-
- ///
- /// Loads in plugin assemblies and script plugins
- ///
- void Load();
}
}
diff --git a/SharedLibraryCore/ScriptPlugin.cs b/SharedLibraryCore/ScriptPlugin.cs
index f7279b69..c26e1461 100644
--- a/SharedLibraryCore/ScriptPlugin.cs
+++ b/SharedLibraryCore/ScriptPlugin.cs
@@ -18,46 +18,110 @@ namespace SharedLibraryCore
public string Author { get; set; }
+ public FileSystemWatcher Watcher { get; private set; }
+
private Engine ScriptEngine;
- private readonly string FileName;
- private IManager Manager;
- private readonly FileSystemWatcher _watcher;
+ private readonly string _fileName;
private readonly SemaphoreSlim _fileChanging;
private bool successfullyLoaded;
- public ScriptPlugin(string fileName)
+ public ScriptPlugin(string filename)
{
- FileName = fileName;
- _fileChanging = new SemaphoreSlim(1, 1);
- _watcher = new FileSystemWatcher()
+ _fileName = filename;
+ Watcher = new FileSystemWatcher()
{
Path = $"{Utilities.OperatingDirectory}Plugins{Path.DirectorySeparatorChar}",
NotifyFilter = NotifyFilters.Size,
- Filter = fileName.Split(Path.DirectorySeparatorChar).Last()
+ Filter = _fileName.Split(Path.DirectorySeparatorChar).Last()
};
- _watcher.Changed += Watcher_Changed;
- _watcher.EnableRaisingEvents = true;
+ Watcher.EnableRaisingEvents = true;
+ _fileChanging = new SemaphoreSlim(1, 1);
}
~ScriptPlugin()
{
- _watcher.Dispose();
+ Watcher.Dispose();
_fileChanging.Dispose();
}
- private async void Watcher_Changed(object sender, FileSystemEventArgs e)
+
+ public async Task Initialize(IManager manager)
{
+ await _fileChanging.WaitAsync();
+
try
{
- await _fileChanging.WaitAsync();
- await Initialize(Manager);
+ // for some reason we get an event trigger when the file is not finished being modified.
+ // this must have been a change in .NET CORE 3.x
+ // so if the new file is empty we can't process it yet
+ if (new FileInfo(_fileName).Length == 0L)
+ {
+ return;
+ }
+
+ bool firstRun = ScriptEngine == null;
+
+ // it's been loaded before so we need to call the unload event
+ if (!firstRun)
+ {
+ await OnUnloadAsync();
+ }
+
+ successfullyLoaded = false;
+ string script;
+
+ using (var stream = new FileStream(_fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
+ {
+ using (var reader = new StreamReader(stream, Encoding.Default))
+ {
+ script = await reader.ReadToEndAsync();
+ }
+ }
+
+ ScriptEngine = new Engine(cfg =>
+ cfg.AllowClr(new[]
+ {
+ typeof(System.Net.Http.HttpClient).Assembly,
+ typeof(EFClient).Assembly,
+ typeof(Utilities).Assembly,
+ typeof(Encoding).Assembly
+ })
+ .CatchClrExceptions());
+
+ ScriptEngine.Execute(script);
+ ScriptEngine.SetValue("_localization", Utilities.CurrentLocalization);
+ dynamic pluginObject = ScriptEngine.GetValue("plugin").ToObject();
+
+ Author = pluginObject.author;
+ Name = pluginObject.name;
+ Version = (float)pluginObject.version;
+
+ try
+ {
+ if (pluginObject.isParser)
+ {
+ await OnLoadAsync(manager);
+ IEventParser eventParser = (IEventParser)ScriptEngine.GetValue("eventParser").ToObject();
+ IRConParser rconParser = (IRConParser)ScriptEngine.GetValue("rconParser").ToObject();
+ manager.AdditionalEventParsers.Add(eventParser);
+ manager.AdditionalRConParsers.Add(rconParser);
+ }
+ }
+ catch { }
+
+
+ if (!firstRun)
+ {
+ await OnLoadAsync(manager);
+ }
+
+ successfullyLoaded = true;
}
- catch (Exception ex)
+ catch
{
- Manager.GetLogger(0).WriteError(Utilities.CurrentLocalization.LocalizationIndex["PLUGIN_IMPORTER_ERROR"].FormatExt(Name));
- Manager.GetLogger(0).WriteDebug(ex.Message);
+ throw;
}
finally
@@ -69,104 +133,20 @@ namespace SharedLibraryCore
}
}
- public async Task Initialize(IManager mgr)
- {
- // for some reason we get an event trigger when the file is not finished being modified.
- // this must have been a change in .NET CORE 3.x
- // so if the new file is empty we can't process it yet
- if (new FileInfo(FileName).Length == 0L)
- {
- return;
- }
-
- bool firstRun = ScriptEngine == null;
-
- // it's been loaded before so we need to call the unload event
- if (!firstRun)
- {
- await OnUnloadAsync();
- }
-
- successfullyLoaded = false;
- Manager = mgr;
- string script;
-
- using (var stream = new FileStream(FileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
- {
- using (var reader = new StreamReader(stream, Encoding.Default))
- {
- script = await reader.ReadToEndAsync();
- }
- }
-
- ScriptEngine = new Engine(cfg =>
- cfg.AllowClr(new[]
- {
- typeof(System.Net.Http.HttpClient).Assembly,
- typeof(EFClient).Assembly,
- typeof(Utilities).Assembly,
- typeof(Encoding).Assembly
- })
- .CatchClrExceptions());
-
- ScriptEngine.Execute(script);
- ScriptEngine.SetValue("_localization", Utilities.CurrentLocalization);
- dynamic pluginObject = ScriptEngine.GetValue("plugin").ToObject();
-
- Author = pluginObject.author;
- Name = pluginObject.name;
- Version = (float)pluginObject.version;
-
- try
- {
- if(pluginObject.isParser)
- {
- await OnLoadAsync(mgr);
- IEventParser eventParser = (IEventParser)ScriptEngine.GetValue("eventParser").ToObject();
- IRConParser rconParser = (IRConParser)ScriptEngine.GetValue("rconParser").ToObject();
- Manager.AdditionalEventParsers.Add(eventParser);
- Manager.AdditionalRConParsers.Add(rconParser);
- }
- }
- catch { }
-
-
- if (!firstRun)
- {
- await OnLoadAsync(mgr);
- }
-
- successfullyLoaded = true;
- }
-
public async Task OnEventAsync(GameEvent E, Server S)
{
if (successfullyLoaded)
{
- try
- {
- await _fileChanging.WaitAsync();
- ScriptEngine.SetValue("_gameEvent", E);
- ScriptEngine.SetValue("_server", S);
- ScriptEngine.SetValue("_IW4MAdminClient", Utilities.IW4MAdminClient(S));
- ScriptEngine.Execute("plugin.onEventAsync(_gameEvent, _server)").GetCompletionValue();
- }
-
- catch { }
-
- finally
- {
- if (_fileChanging.CurrentCount == 0)
- {
- _fileChanging.Release(1);
- }
- }
+ ScriptEngine.SetValue("_gameEvent", E);
+ ScriptEngine.SetValue("_server", S);
+ ScriptEngine.SetValue("_IW4MAdminClient", Utilities.IW4MAdminClient(S));
+ await Task.FromResult(ScriptEngine.Execute("plugin.onEventAsync(_gameEvent, _server)").GetCompletionValue());
}
}
public Task OnLoadAsync(IManager manager)
{
- Manager.GetLogger(0).WriteDebug($"OnLoad executing for {Name}");
+ manager.GetLogger(0).WriteDebug($"OnLoad executing for {Name}");
ScriptEngine.SetValue("_manager", manager);
return Task.FromResult(ScriptEngine.Execute("plugin.onLoadAsync(_manager)").GetCompletionValue());
}
@@ -181,7 +161,6 @@ namespace SharedLibraryCore
{
if (successfullyLoaded)
{
- Manager.GetLogger(0).WriteDebug($"OnUnLoad executing for {Name}");
await Task.FromResult(ScriptEngine.Execute("plugin.onUnloadAsync()").GetCompletionValue());
}
}
diff --git a/WebfrontCore/Controllers/ServerController.cs b/WebfrontCore/Controllers/ServerController.cs
index f73506c6..3c1fc308 100644
--- a/WebfrontCore/Controllers/ServerController.cs
+++ b/WebfrontCore/Controllers/ServerController.cs
@@ -21,7 +21,7 @@ namespace WebfrontCore.Controllers
if (s == null)
{
- return View("Error", "Invalid server!");
+ return NotFound();
}
var serverInfo = new ServerInfo()