More async init, add proper NLog target for WPF and free console in UI mode

This commit is contained in:
John Gross
2018-01-21 21:23:11 -08:00
parent c5e1dd7c3a
commit 0328876d50
12 changed files with 133 additions and 19 deletions

View File

@@ -11,15 +11,16 @@
<target xsi:type="File" name="chat" layout="${longdate} ${message}" fileName="Logs\Chat.log" /> <target xsi:type="File" name="chat" layout="${longdate} ${message}" fileName="Logs\Chat.log" />
<target xsi:type="ColoredConsole" name="console" layout="${var:logStamp} ${logger:shortName=true}: ${var:logContent}" /> <target xsi:type="ColoredConsole" name="console" layout="${var:logStamp} ${logger:shortName=true}: ${var:logContent}" />
<target xsi:type="File" name="patch" layout="${var:logContent}" fileName="Logs\patch.log"/> <target xsi:type="File" name="patch" layout="${var:logContent}" fileName="Logs\patch.log"/>
<target xsi:type="FlowDocument" name="wpf" layout="${var:logStamp} ${logger:shortName=true}: ${var:logContent}" />
</targets> </targets>
<rules> <rules>
<logger name="Keen" minlevel="Warn" writeTo="main"/> <logger name="Keen" minlevel="Warn" writeTo="main"/>
<logger name="Keen" minlevel="Info" writeTo="console"/> <logger name="Keen" minlevel="Info" writeTo="console, wpf"/>
<logger name="Keen" minlevel="Debug" writeTo="keen" final="true" /> <logger name="Keen" minlevel="Debug" writeTo="keen" final="true" />
<logger name="Keen" writeTo="null" final="true" /> <logger name="Keen" writeTo="null" final="true" />
<logger name="*" minlevel="Info" writeTo="main, console" /> <logger name="*" minlevel="Info" writeTo="main, console, wpf" />
<logger name="Chat" minlevel="Info" writeTo="chat" /> <logger name="Chat" minlevel="Info" writeTo="chat" />
<!--<logger name="Torch.Managers.PatchManager.*" minlevel="Trace" writeTo="patch"/>--> <!--<logger name="Torch.Managers.PatchManager.*" minlevel="Trace" writeTo="patch"/>-->
</rules> </rules>

View File

@@ -149,6 +149,11 @@ namespace Torch.API
/// Path of the dedicated instance folder. /// Path of the dedicated instance folder.
/// </summary> /// </summary>
string InstancePath { get; } string InstancePath { get; }
/// <summary>
/// Raised when the server's Init() method has completed.
/// </summary>
event Action<ITorchServer> Initialized;
} }
/// <summary> /// <summary>

View File

@@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Documents;
using System.Windows.Media;
using NLog;
using NLog.Targets;
namespace Torch.Server
{
[Target("flowDocument")]
public sealed class FlowDocumentTarget : TargetWithLayout
{
private FlowDocument _document = new FlowDocument { Background = new SolidColorBrush(Colors.Black) };
private readonly Paragraph _paragraph = new Paragraph();
public FlowDocument Document => _document;
public FlowDocumentTarget()
{
_document.Blocks.Add(_paragraph);
}
/// <inheritdoc />
protected override void Write(LogEventInfo logEvent)
{
_document.Dispatcher.BeginInvoke(() =>
{
var message = $"{Layout.Render(logEvent)}\n";
_paragraph.Inlines.Add(new Run(message) {Foreground = LogLevelColors[logEvent.Level]});
});
}
private static readonly Dictionary<LogLevel, SolidColorBrush> LogLevelColors = new Dictionary<LogLevel, SolidColorBrush>
{
[LogLevel.Trace] = new SolidColorBrush(Colors.DimGray),
[LogLevel.Debug] = new SolidColorBrush(Colors.DarkGray),
[LogLevel.Info] = new SolidColorBrush(Colors.White),
[LogLevel.Warn] = new SolidColorBrush(Colors.Magenta),
[LogLevel.Error] = new SolidColorBrush(Colors.Yellow),
[LogLevel.Fatal] = new SolidColorBrush(Colors.Red),
};
}
}

View File

@@ -12,6 +12,7 @@ using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Threading; using System.Windows.Threading;
using NLog; using NLog;
using NLog.Targets;
using Torch.Utils; using Torch.Utils;
namespace Torch.Server namespace Torch.Server
@@ -85,23 +86,26 @@ quit";
public void Run() public void Run()
{ {
_server = new TorchServer(_config); _server = new TorchServer(_config);
try try
{ {
_server.Init(); var init = Task.Run(() => _server.Init());
if (!_config.NoGui) if (!_config.NoGui)
{ {
if (_config.Autostart) if (_config.Autostart)
Task.Run(() => _server.Start()); init.ContinueWith(x => _server.Start());
Log.Info("Showing UI");
Console.SetOut(TextWriter.Null);
NativeMethods.FreeConsole();
new TorchUI(_server).ShowDialog(); new TorchUI(_server).ShowDialog();
} }
else else
{ {
init.Wait();
_server.Start(); _server.Start();
} }
} }
finally catch
{ {
if (_server.IsRunning) if (_server.IsRunning)
_server.Stop(); _server.Stop();

View File

@@ -2,6 +2,7 @@
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
using System.ServiceProcess; using System.ServiceProcess;
using NLog.Targets;
using Torch.Utils; using Torch.Utils;
namespace Torch.Server namespace Torch.Server
@@ -14,6 +15,7 @@ namespace Torch.Server
[STAThread] [STAThread]
public static void Main(string[] args) public static void Main(string[] args)
{ {
Target.Register<FlowDocumentTarget>("FlowDocument");
//Ensures that all the files are downloaded in the Torch directory. //Ensures that all the files are downloaded in the Torch directory.
var workingDir = new FileInfo(typeof(Program).Assembly.Location).Directory.ToString(); var workingDir = new FileInfo(typeof(Program).Assembly.Location).Directory.ToString();
var binDir = Path.Combine(workingDir, "DedicatedServer64"); var binDir = Path.Combine(workingDir, "DedicatedServer64");

View File

@@ -15,6 +15,21 @@
<TargetFrameworkProfile /> <TargetFrameworkProfile />
<NuGetPackageImportStamp> <NuGetPackageImportStamp>
</NuGetPackageImportStamp> </NuGetPackageImportStamp>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
@@ -195,6 +210,7 @@
<Compile Include="..\Versioning\AssemblyVersion.cs"> <Compile Include="..\Versioning\AssemblyVersion.cs">
<Link>Properties\AssemblyVersion.cs</Link> <Link>Properties\AssemblyVersion.cs</Link>
</Compile> </Compile>
<Compile Include="FlowDocumentTarget.cs" />
<Compile Include="ListBoxExtensions.cs" /> <Compile Include="ListBoxExtensions.cs" />
<Compile Include="Managers\EntityControlManager.cs" /> <Compile Include="Managers\EntityControlManager.cs" />
<Compile Include="Managers\MultiplayerManagerDedicated.cs" /> <Compile Include="Managers\MultiplayerManagerDedicated.cs" />
@@ -411,6 +427,18 @@
<LastGenOutput>SessionSettingsViewModel.cs</LastGenOutput> <LastGenOutput>SessionSettingsViewModel.cs</LastGenOutput>
</Content> </Content>
</ItemGroup> </ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.6.1">
<Visible>False</Visible>
<ProductName>Microsoft .NET Framework 4.6.1 %28x86 and x64%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\TransformOnBuild.targets" /> <Import Project="$(SolutionDir)\TransformOnBuild.targets" />
<PropertyGroup> <PropertyGroup>

View File

@@ -75,6 +75,8 @@ namespace Torch.Server
private bool _hasRun; private bool _hasRun;
public event Action<ITorchServer> Initialized;
/// <inheritdoc /> /// <inheritdoc />
public InstanceManager DedicatedInstance { get; } public InstanceManager DedicatedInstance { get; }
@@ -112,13 +114,15 @@ namespace Torch.Server
/// <inheritdoc /> /// <inheritdoc />
public override void Init() public override void Init()
{ {
Log.Info("Initializing server");
Sandbox.Engine.Platform.Game.IsDedicated = true; Sandbox.Engine.Platform.Game.IsDedicated = true;
base.Init(); base.Init();
Log.Info($"Init server '{Config.InstanceName}' at '{Config.InstancePath}'");
Managers.GetManager<ITorchSessionManager>().SessionStateChanged += OnSessionStateChanged; Managers.GetManager<ITorchSessionManager>().SessionStateChanged += OnSessionStateChanged;
GetManager<InstanceManager>().LoadInstance(Config.InstancePath); GetManager<InstanceManager>().LoadInstance(Config.InstancePath);
CanRun = true; CanRun = true;
Initialized?.Invoke(this);
Log.Info($"Initialized server '{Config.InstanceName}' at '{Config.InstancePath}'");
} }
private void OnSessionStateChanged(ITorchSession session, TorchSessionState newState) private void OnSessionStateChanged(ITorchSession session, TorchSessionState newState)
@@ -216,7 +220,8 @@ namespace Torch.Server
public override void Update() public override void Update()
{ {
base.Update(); base.Update();
SimulationRatio = Sync.ServerSimulationRatio; // Stops 1.00-1.02 flicker.
SimulationRatio = Math.Min(Sync.ServerSimulationRatio, 1);
var elapsed = TimeSpan.FromSeconds(Math.Floor(_uptime.Elapsed.TotalSeconds)); var elapsed = TimeSpan.FromSeconds(Math.Floor(_uptime.Elapsed.TotalSeconds));
ElapsedPlayTime = elapsed; ElapsedPlayTime = elapsed;

View File

@@ -34,7 +34,7 @@ namespace Torch.Server
/// </summary> /// </summary>
public partial class ChatControl : UserControl public partial class ChatControl : UserControl
{ {
private TorchBase _server; private ITorchServer _server;
public ChatControl() public ChatControl()
{ {
@@ -43,13 +43,19 @@ namespace Torch.Server
public void BindServer(ITorchServer server) public void BindServer(ITorchServer server)
{ {
_server = (TorchBase)server; _server = server;
server.Initialized += Server_Initialized ;
}
private void Server_Initialized(ITorchServer obj)
{
Dispatcher.InvokeAsync(() => Dispatcher.InvokeAsync(() =>
{ {
ChatItems.Inlines.Clear(); ChatItems.Inlines.Clear();
}); });
var sessionManager = server.Managers.GetManager<ITorchSessionManager>(); var sessionManager = _server.Managers.GetManager<ITorchSessionManager>();
if (sessionManager != null) if (sessionManager != null)
sessionManager.SessionStateChanged += SessionStateChanged; sessionManager.SessionStateChanged += SessionStateChanged;
} }

View File

@@ -47,8 +47,12 @@ namespace Torch.Server
public void BindServer(ITorchServer server) public void BindServer(ITorchServer server)
{ {
_server = server; _server = server;
_server.Initialized += Server_Initialized ;
}
var sessionManager = server.Managers.GetManager<ITorchSessionManager>(); private void Server_Initialized(ITorchServer obj)
{
var sessionManager = _server.Managers.GetManager<ITorchSessionManager>();
sessionManager.SessionStateChanged += SessionStateChanged; sessionManager.SessionStateChanged += SessionStateChanged;
} }

View File

@@ -38,9 +38,18 @@ namespace Torch.Server.Views
public void BindServer(ITorchServer server) public void BindServer(ITorchServer server)
{ {
_server = server; _server = server;
_plugins = _server.Managers.GetManager<PluginManager>(); _server.Initialized += Server_Initialized;
var pluginManager = new PluginManagerViewModel(_plugins); }
DataContext = pluginManager;
private void Server_Initialized(ITorchServer obj)
{
Dispatcher.InvokeAsync(() =>
{
_plugins = _server.Managers.GetManager<PluginManager>();
var pluginManager = new PluginManagerViewModel(_plugins);
DataContext = pluginManager;
});
} }
private void OpenFolder_OnClick(object sender, RoutedEventArgs e) private void OpenFolder_OnClick(object sender, RoutedEventArgs e)

View File

@@ -57,7 +57,7 @@
</Label> </Label>
</StackPanel> </StackPanel>
<TabControl Grid.Row="2" Height="Auto" x:Name="TabControl" Margin="5,10,5,5"> <TabControl Grid.Row="2" Height="Auto" x:Name="TabControl" Margin="5,10,5,5">
<TabItem Header="Console"> <TabItem Header="Log">
<RichTextBox x:Name="ConsoleText" VerticalScrollBarVisibility="Visible" FontFamily="Consolas"/> <RichTextBox x:Name="ConsoleText" VerticalScrollBarVisibility="Visible" FontFamily="Consolas"/>
</TabItem> </TabItem>
<TabItem Header="Configuration"> <TabItem Header="Configuration">

View File

@@ -8,10 +8,12 @@ using System.Timers;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Data; using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using System.Windows.Navigation; using System.Windows.Navigation;
using System.Windows.Shapes; using System.Windows.Shapes;
using NLog;
using Sandbox; using Sandbox;
using Torch.API; using Torch.API;
using Torch.Server.Managers; using Torch.Server.Managers;
@@ -36,6 +38,8 @@ namespace Torch.Server
DataContext = server; DataContext = server;
InitializeComponent(); InitializeComponent();
AttachConsole();
Left = _config.WindowPosition.X; Left = _config.WindowPosition.X;
Top = _config.WindowPosition.Y; Top = _config.WindowPosition.Y;
Width = _config.WindowSize.X; Width = _config.WindowSize.X;
@@ -45,13 +49,13 @@ namespace Torch.Server
PlayerList.BindServer(server); PlayerList.BindServer(server);
Plugins.BindServer(server); Plugins.BindServer(server);
LoadConfig((TorchConfig)server.Config); LoadConfig((TorchConfig)server.Config);
AttachConsole();
} }
private void AttachConsole() private void AttachConsole()
{ {
Console.SetOut(new MultiTextWriter(new RichTextBoxWriter(ConsoleText), Console.Out)); var doc = LogManager.Configuration.FindTargetByName<FlowDocumentTarget>("wpf")?.Document;
ConsoleText.Document = doc ?? new FlowDocument(new Paragraph(new Run("No target!")));
ConsoleText.TextChanged += (sender, args) => ConsoleText.ScrollToEnd();
} }
public void LoadConfig(TorchConfig config) public void LoadConfig(TorchConfig config)