Address some .NET 6 oddities and allow webfront startup without servers being monitored

This commit is contained in:
RaidMax 2022-01-26 14:42:23 -06:00
parent a602e8caed
commit 7171b3753e
4 changed files with 76 additions and 58 deletions

View File

@ -13,4 +13,5 @@ if not exist "%TargetDir%Plugins" (
md "%TargetDir%Plugins" md "%TargetDir%Plugins"
) )
xcopy /y "%SolutionDir%Build\Plugins" "%TargetDir%Plugins\" xcopy /y "%SolutionDir%Build\Plugins" "%TargetDir%Plugins\"
del "%TargetDir%Plugins\SQLite*"

View File

@ -40,7 +40,7 @@ namespace IW4MAdmin.Application
{ {
public class Program public class Program
{ {
public static BuildNumber Version { get; private set; } = BuildNumber.Parse(Utilities.GetVersionAsString()); public static BuildNumber Version { get; } = BuildNumber.Parse(Utilities.GetVersionAsString());
public static ApplicationManager ServerManager; public static ApplicationManager ServerManager;
private static Task ApplicationTask; private static Task ApplicationTask;
private static ServiceProvider serviceProvider; private static ServiceProvider serviceProvider;
@ -56,7 +56,7 @@ namespace IW4MAdmin.Application
Console.OutputEncoding = Encoding.UTF8; Console.OutputEncoding = Encoding.UTF8;
Console.ForegroundColor = ConsoleColor.Gray; Console.ForegroundColor = ConsoleColor.Gray;
Console.CancelKeyPress += new ConsoleCancelEventHandler(OnCancelKey); Console.CancelKeyPress += OnCancelKey;
Console.WriteLine("====================================================="); Console.WriteLine("=====================================================");
Console.WriteLine(" IW4MAdmin"); Console.WriteLine(" IW4MAdmin");
@ -93,8 +93,8 @@ namespace IW4MAdmin.Application
var logger = BuildDefaultLogger<Program>(new ApplicationConfiguration()); var logger = BuildDefaultLogger<Program>(new ApplicationConfiguration());
Utilities.DefaultLogger = logger; Utilities.DefaultLogger = logger;
IServiceCollection services = null; IServiceCollection services = null;
logger.LogInformation("Begin IW4MAdmin startup. Version is {version} {@args}", Version, args); logger.LogInformation("Begin IW4MAdmin startup. Version is {Version} {@Args}", Version, args);
try try
{ {
// do any needed housekeeping file/folder migrations // do any needed housekeeping file/folder migrations
@ -108,16 +108,23 @@ namespace IW4MAdmin.Application
ServerManager = (ApplicationManager) serviceProvider.GetRequiredService<IManager>(); ServerManager = (ApplicationManager) serviceProvider.GetRequiredService<IManager>();
translationLookup = serviceProvider.GetRequiredService<ITranslationLookup>(); translationLookup = serviceProvider.GetRequiredService<ITranslationLookup>();
await versionChecker.CheckVersion(); ApplicationTask = RunApplicationTasksAsync(logger, services);
await ServerManager.Init(); var tasks = new[]
{
versionChecker.CheckVersion(),
ServerManager.Init(),
ApplicationTask
};
await Task.WhenAll(tasks);
} }
catch (Exception e) catch (Exception e)
{ {
string failMessage = translationLookup == null var failMessage = translationLookup == null
? "Failed to initialize IW4MAdmin" ? "Failed to initialize IW4MAdmin"
: translationLookup["MANAGER_INIT_FAIL"]; : translationLookup["MANAGER_INIT_FAIL"];
string exitMessage = translationLookup == null var exitMessage = translationLookup == null
? "Press enter to exit..." ? "Press enter to exit..."
: translationLookup["MANAGER_EXIT"]; : translationLookup["MANAGER_EXIT"];
@ -137,7 +144,7 @@ namespace IW4MAdmin.Application
.FormatExt(configException.ConfigurationFileName)); .FormatExt(configException.ConfigurationFileName));
} }
foreach (string error in configException.Errors) foreach (var error in configException.Errors)
{ {
Console.WriteLine(error); Console.WriteLine(error);
} }
@ -153,27 +160,12 @@ namespace IW4MAdmin.Application
return; return;
} }
try
{
ApplicationTask = RunApplicationTasksAsync(logger, services);
await ApplicationTask;
}
catch (Exception e)
{
logger.LogCritical(e, "Failed to launch IW4MAdmin");
string failMessage = translationLookup == null
? "Failed to launch IW4MAdmin"
: translationLookup["MANAGER_INIT_FAIL"];
Console.WriteLine($"{failMessage}: {e.GetExceptionInfo()}");
}
if (ServerManager.IsRestartRequested) if (ServerManager.IsRestartRequested)
{ {
goto restart; goto restart;
} }
serviceProvider.Dispose(); await serviceProvider.DisposeAsync();
} }
/// <summary> /// <summary>
@ -190,13 +182,15 @@ namespace IW4MAdmin.Application
// we want to run this one on a manual thread instead of letting the thread pool handle it, // we want to run this one on a manual thread instead of letting the thread pool handle it,
// because we can't exit early from waiting on console input, and it prevents us from restarting // because we can't exit early from waiting on console input, and it prevents us from restarting
var inputThread = new Thread(async () => await ReadConsoleInput(logger)); async void ReadInput() => await ReadConsoleInput(logger);
var inputThread = new Thread(ReadInput);
inputThread.Start(); inputThread.Start();
var tasks = new[] var tasks = new[]
{ {
ServerManager.Start(),
webfrontTask, webfrontTask,
ServerManager.Start(),
serviceProvider.GetRequiredService<IMasterCommunication>() serviceProvider.GetRequiredService<IMasterCommunication>()
.RunUploadStatus(ServerManager.CancellationToken), .RunUploadStatus(ServerManager.CancellationToken),
collectionService.BeginCollectionAsync(cancellationToken: ServerManager.CancellationToken) collectionService.BeginCollectionAsync(cancellationToken: ServerManager.CancellationToken)
@ -208,8 +202,7 @@ namespace IW4MAdmin.Application
logger.LogInformation("Shutdown completed successfully"); logger.LogInformation("Shutdown completed successfully");
Console.WriteLine(Utilities.CurrentLocalization.LocalizationIndex["MANAGER_SHUTDOWN_SUCCESS"]); Console.WriteLine(Utilities.CurrentLocalization.LocalizationIndex["MANAGER_SHUTDOWN_SUCCESS"]);
} }
/// <summary> /// <summary>
/// reads input from the console and executes entered commands on the default server /// reads input from the console and executes entered commands on the default server
/// </summary> /// </summary>
@ -223,7 +216,7 @@ namespace IW4MAdmin.Application
} }
string lastCommand; string lastCommand;
var Origin = Utilities.IW4MAdminClient(ServerManager.Servers[0]); EFClient origin = null;
try try
{ {
@ -231,23 +224,27 @@ namespace IW4MAdmin.Application
{ {
lastCommand = await Console.In.ReadLineAsync(); lastCommand = await Console.In.ReadLineAsync();
if (lastCommand?.Length > 0) if (lastCommand == null)
{ {
if (lastCommand?.Length > 0) continue;
{
GameEvent E = new GameEvent()
{
Type = GameEvent.EventType.Command,
Data = lastCommand,
Origin = Origin,
Owner = ServerManager.Servers[0]
};
ServerManager.AddEvent(E);
await E.WaitAsync(Utilities.DefaultCommandTimeout, ServerManager.CancellationToken);
Console.Write('>');
}
} }
if (!lastCommand.Any())
{
continue;
}
var gameEvent = new GameEvent
{
Type = GameEvent.EventType.Command,
Data = lastCommand,
Origin = origin ??= Utilities.IW4MAdminClient(ServerManager.Servers.FirstOrDefault()),
Owner = ServerManager.Servers[0]
};
ServerManager.AddEvent(gameEvent);
await gameEvent.WaitAsync(Utilities.DefaultCommandTimeout, ServerManager.CancellationToken);
Console.Write('>');
} }
} }
catch (OperationCanceledException) catch (OperationCanceledException)
@ -355,7 +352,7 @@ namespace IW4MAdmin.Application
{ {
appConfig = (ApplicationConfiguration) new ApplicationConfiguration().Generate(); appConfig = (ApplicationConfiguration) new ApplicationConfiguration().Generate();
appConfigHandler.Set(appConfig); appConfigHandler.Set(appConfig);
appConfigHandler.Save(); appConfigHandler.Save().RunSynchronously();
} }
// register override level names // register override level names

View File

@ -4,6 +4,7 @@ using SharedLibraryCore.Exceptions;
using SharedLibraryCore.Interfaces; using SharedLibraryCore.Interfaces;
using System; using System;
using System.IO; using System.IO;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace IW4MAdmin.Application.Misc namespace IW4MAdmin.Application.Misc
@ -15,16 +16,23 @@ namespace IW4MAdmin.Application.Misc
public class BaseConfigurationHandler<T> : IConfigurationHandler<T> where T : IBaseConfiguration public class BaseConfigurationHandler<T> : IConfigurationHandler<T> where T : IBaseConfiguration
{ {
T _configuration; T _configuration;
private readonly SemaphoreSlim _onSaving;
public BaseConfigurationHandler(string fn) public BaseConfigurationHandler(string fn)
{ {
_onSaving = new SemaphoreSlim(1, 1);
FileName = Path.Join(Utilities.OperatingDirectory, "Configuration", $"{fn}.json"); FileName = Path.Join(Utilities.OperatingDirectory, "Configuration", $"{fn}.json");
Build(); Build();
} }
public BaseConfigurationHandler() : this(typeof(T).Name) public BaseConfigurationHandler() : this(typeof(T).Name)
{ {
_onSaving = new SemaphoreSlim(1, 1);
}
~BaseConfigurationHandler()
{
_onSaving.Dispose();
} }
public string FileName { get; } public string FileName { get; }
@ -54,14 +62,26 @@ namespace IW4MAdmin.Application.Misc
public async Task Save() public async Task Save()
{ {
var settings = new JsonSerializerSettings() try
{ {
Formatting = Formatting.Indented await _onSaving.WaitAsync();
}; var settings = new JsonSerializerSettings()
settings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter()); {
Formatting = Formatting.Indented
};
settings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());
var appConfigJson = JsonConvert.SerializeObject(_configuration, settings); var appConfigJson = JsonConvert.SerializeObject(_configuration, settings);
await File.WriteAllTextAsync(FileName, appConfigJson); await File.WriteAllTextAsync(FileName, appConfigJson);
}
finally
{
if (_onSaving.CurrentCount == 0)
{
_onSaving.Release(1);
}
}
} }
public T Configuration() public T Configuration()

View File

@ -268,17 +268,17 @@ namespace IW4MAdmin.Application.Misc
} }
} }
public Task OnLoadAsync(IManager manager) public async Task OnLoadAsync(IManager manager)
{ {
_logger.LogDebug("OnLoad executing for {name}", Name); _logger.LogDebug("OnLoad executing for {name}", Name);
_scriptEngine.SetValue("_manager", manager); _scriptEngine.SetValue("_manager", manager);
return Task.FromResult(_scriptEngine.Execute("plugin.onLoadAsync(_manager)").GetCompletionValue()); await Task.FromResult(_scriptEngine.Execute("plugin.onLoadAsync(_manager)").GetCompletionValue());
} }
public Task OnTickAsync(Server S) public async Task OnTickAsync(Server S)
{ {
_scriptEngine.SetValue("_server", S); _scriptEngine.SetValue("_server", S);
return Task.FromResult(_scriptEngine.Execute("plugin.onTickAsync(_server)").GetCompletionValue()); await Task.FromResult(_scriptEngine.Execute("plugin.onTickAsync(_server)").GetCompletionValue());
} }
public async Task OnUnloadAsync() public async Task OnUnloadAsync()