diff --git a/NLog.config b/NLog.config
index d1c94c7..c47561e 100644
--- a/NLog.config
+++ b/NLog.config
@@ -11,15 +11,16 @@
+
-
+
-
+
diff --git a/Torch.API/ITorchBase.cs b/Torch.API/ITorchBase.cs
index 1afdf9d..b8b2e68 100644
--- a/Torch.API/ITorchBase.cs
+++ b/Torch.API/ITorchBase.cs
@@ -149,6 +149,11 @@ namespace Torch.API
/// Path of the dedicated instance folder.
///
string InstancePath { get; }
+
+ ///
+ /// Raised when the server's Init() method has completed.
+ ///
+ event Action Initialized;
}
///
diff --git a/Torch.Server/FlowDocumentTarget.cs b/Torch.Server/FlowDocumentTarget.cs
new file mode 100644
index 0000000..daef655
--- /dev/null
+++ b/Torch.Server/FlowDocumentTarget.cs
@@ -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);
+ }
+
+ ///
+ 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 LogLevelColors = new Dictionary
+ {
+ [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),
+ };
+ }
+}
diff --git a/Torch.Server/Initializer.cs b/Torch.Server/Initializer.cs
index ffe5503..d3f9205 100644
--- a/Torch.Server/Initializer.cs
+++ b/Torch.Server/Initializer.cs
@@ -12,6 +12,7 @@ using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading;
using NLog;
+using NLog.Targets;
using Torch.Utils;
namespace Torch.Server
@@ -85,23 +86,26 @@ quit";
public void Run()
{
_server = new TorchServer(_config);
-
try
{
- _server.Init();
+ var init = Task.Run(() => _server.Init());
if (!_config.NoGui)
{
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();
}
else
{
+ init.Wait();
_server.Start();
}
}
- finally
+ catch
{
if (_server.IsRunning)
_server.Stop();
diff --git a/Torch.Server/Program.cs b/Torch.Server/Program.cs
index 401696a..99fad9b 100644
--- a/Torch.Server/Program.cs
+++ b/Torch.Server/Program.cs
@@ -2,6 +2,7 @@
using System.IO;
using System.Reflection;
using System.ServiceProcess;
+using NLog.Targets;
using Torch.Utils;
namespace Torch.Server
@@ -14,6 +15,7 @@ namespace Torch.Server
[STAThread]
public static void Main(string[] args)
{
+ Target.Register("FlowDocument");
//Ensures that all the files are downloaded in the Torch directory.
var workingDir = new FileInfo(typeof(Program).Assembly.Location).Directory.ToString();
var binDir = Path.Combine(workingDir, "DedicatedServer64");
diff --git a/Torch.Server/Torch.Server.csproj b/Torch.Server/Torch.Server.csproj
index ff54836..4400e35 100644
--- a/Torch.Server/Torch.Server.csproj
+++ b/Torch.Server/Torch.Server.csproj
@@ -15,6 +15,21 @@
+ publish\
+ true
+ Disk
+ false
+ Foreground
+ 7
+ Days
+ false
+ false
+ true
+ 0
+ 1.0.0.%2a
+ false
+ false
+ true
true
@@ -195,6 +210,7 @@
Properties\AssemblyVersion.cs
+
@@ -411,6 +427,18 @@
SessionSettingsViewModel.cs
+
+
+ False
+ Microsoft .NET Framework 4.6.1 %28x86 and x64%29
+ true
+
+
+ False
+ .NET Framework 3.5 SP1
+ false
+
+
diff --git a/Torch.Server/TorchServer.cs b/Torch.Server/TorchServer.cs
index 5f1ac45..0e76378 100644
--- a/Torch.Server/TorchServer.cs
+++ b/Torch.Server/TorchServer.cs
@@ -75,6 +75,8 @@ namespace Torch.Server
private bool _hasRun;
+ public event Action Initialized;
+
///
public InstanceManager DedicatedInstance { get; }
@@ -112,13 +114,15 @@ namespace Torch.Server
///
public override void Init()
{
+ Log.Info("Initializing server");
Sandbox.Engine.Platform.Game.IsDedicated = true;
base.Init();
- Log.Info($"Init server '{Config.InstanceName}' at '{Config.InstancePath}'");
Managers.GetManager().SessionStateChanged += OnSessionStateChanged;
GetManager().LoadInstance(Config.InstancePath);
CanRun = true;
+ Initialized?.Invoke(this);
+ Log.Info($"Initialized server '{Config.InstanceName}' at '{Config.InstancePath}'");
}
private void OnSessionStateChanged(ITorchSession session, TorchSessionState newState)
@@ -216,7 +220,8 @@ namespace Torch.Server
public override void 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));
ElapsedPlayTime = elapsed;
diff --git a/Torch.Server/Views/ChatControl.xaml.cs b/Torch.Server/Views/ChatControl.xaml.cs
index d88d8e4..5cce943 100644
--- a/Torch.Server/Views/ChatControl.xaml.cs
+++ b/Torch.Server/Views/ChatControl.xaml.cs
@@ -34,7 +34,7 @@ namespace Torch.Server
///
public partial class ChatControl : UserControl
{
- private TorchBase _server;
+ private ITorchServer _server;
public ChatControl()
{
@@ -43,13 +43,19 @@ namespace Torch.Server
public void BindServer(ITorchServer server)
{
- _server = (TorchBase)server;
+ _server = server;
+
+ server.Initialized += Server_Initialized ;
+ }
+
+ private void Server_Initialized(ITorchServer obj)
+ {
Dispatcher.InvokeAsync(() =>
{
ChatItems.Inlines.Clear();
});
- var sessionManager = server.Managers.GetManager();
+ var sessionManager = _server.Managers.GetManager();
if (sessionManager != null)
sessionManager.SessionStateChanged += SessionStateChanged;
}
diff --git a/Torch.Server/Views/PlayerListControl.xaml.cs b/Torch.Server/Views/PlayerListControl.xaml.cs
index 49c40a7..d7c2179 100644
--- a/Torch.Server/Views/PlayerListControl.xaml.cs
+++ b/Torch.Server/Views/PlayerListControl.xaml.cs
@@ -47,8 +47,12 @@ namespace Torch.Server
public void BindServer(ITorchServer server)
{
_server = server;
+ _server.Initialized += Server_Initialized ;
+ }
- var sessionManager = server.Managers.GetManager();
+ private void Server_Initialized(ITorchServer obj)
+ {
+ var sessionManager = _server.Managers.GetManager();
sessionManager.SessionStateChanged += SessionStateChanged;
}
diff --git a/Torch.Server/Views/PluginsControl.xaml.cs b/Torch.Server/Views/PluginsControl.xaml.cs
index 6b54f26..b990f5b 100644
--- a/Torch.Server/Views/PluginsControl.xaml.cs
+++ b/Torch.Server/Views/PluginsControl.xaml.cs
@@ -38,9 +38,18 @@ namespace Torch.Server.Views
public void BindServer(ITorchServer server)
{
_server = server;
- _plugins = _server.Managers.GetManager();
- var pluginManager = new PluginManagerViewModel(_plugins);
- DataContext = pluginManager;
+ _server.Initialized += Server_Initialized;
+ }
+
+ private void Server_Initialized(ITorchServer obj)
+ {
+ Dispatcher.InvokeAsync(() =>
+ {
+ _plugins = _server.Managers.GetManager();
+ var pluginManager = new PluginManagerViewModel(_plugins);
+ DataContext = pluginManager;
+ });
+
}
private void OpenFolder_OnClick(object sender, RoutedEventArgs e)
diff --git a/Torch.Server/Views/TorchUI.xaml b/Torch.Server/Views/TorchUI.xaml
index 5f61026..bdda27d 100644
--- a/Torch.Server/Views/TorchUI.xaml
+++ b/Torch.Server/Views/TorchUI.xaml
@@ -57,7 +57,7 @@
-
+
diff --git a/Torch.Server/Views/TorchUI.xaml.cs b/Torch.Server/Views/TorchUI.xaml.cs
index e3980c1..a274676 100644
--- a/Torch.Server/Views/TorchUI.xaml.cs
+++ b/Torch.Server/Views/TorchUI.xaml.cs
@@ -8,10 +8,12 @@ using System.Timers;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
+using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
+using NLog;
using Sandbox;
using Torch.API;
using Torch.Server.Managers;
@@ -36,6 +38,8 @@ namespace Torch.Server
DataContext = server;
InitializeComponent();
+ AttachConsole();
+
Left = _config.WindowPosition.X;
Top = _config.WindowPosition.Y;
Width = _config.WindowSize.X;
@@ -45,13 +49,13 @@ namespace Torch.Server
PlayerList.BindServer(server);
Plugins.BindServer(server);
LoadConfig((TorchConfig)server.Config);
-
- AttachConsole();
}
private void AttachConsole()
{
- Console.SetOut(new MultiTextWriter(new RichTextBoxWriter(ConsoleText), Console.Out));
+ var doc = LogManager.Configuration.FindTargetByName("wpf")?.Document;
+ ConsoleText.Document = doc ?? new FlowDocument(new Paragraph(new Run("No target!")));
+ ConsoleText.TextChanged += (sender, args) => ConsoleText.ScrollToEnd();
}
public void LoadConfig(TorchConfig config)