Fix start/stop buttons, improve DS init order, add console tab
This commit is contained in:
@@ -9,6 +9,7 @@ using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Threading;
|
||||
using NLog;
|
||||
using Torch.Utils;
|
||||
@@ -84,27 +85,21 @@ quit";
|
||||
public void Run()
|
||||
{
|
||||
_server = new TorchServer(_config);
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
var initTask = Task.Run(() => { _server.Init(); });
|
||||
_server.Init();
|
||||
if (!_config.NoGui)
|
||||
{
|
||||
_server.Init();
|
||||
|
||||
if (!_config.NoGui)
|
||||
{
|
||||
var ui = new TorchUI(_server);
|
||||
if (_config.Autostart)
|
||||
_server.Start();
|
||||
ui.ShowDialog();
|
||||
}
|
||||
else
|
||||
_server.Start();
|
||||
if (_config.Autostart)
|
||||
Task.Run(() => _server.Start());
|
||||
|
||||
new TorchUI(_server).ShowDialog();
|
||||
}
|
||||
else
|
||||
{
|
||||
initTask.Wait();
|
||||
_server.Start();
|
||||
}
|
||||
}
|
||||
@@ -116,101 +111,105 @@ quit";
|
||||
}
|
||||
}
|
||||
|
||||
private TorchConfig InitConfig()
|
||||
private TorchConfig InitConfig()
|
||||
{
|
||||
var configName = "Torch.cfg";
|
||||
var configPath = Path.Combine(Directory.GetCurrentDirectory(), configName);
|
||||
if (File.Exists(configName))
|
||||
{
|
||||
var configName = "Torch.cfg";
|
||||
var configPath = Path.Combine(Directory.GetCurrentDirectory(), configName);
|
||||
if (File.Exists(configName))
|
||||
{
|
||||
Log.Info($"Loading config {configPath}");
|
||||
return TorchConfig.LoadFrom(configPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Info($"Generating default config at {configPath}");
|
||||
var config = new TorchConfig {InstancePath = Path.GetFullPath("Instance")};
|
||||
config.Save(configPath);
|
||||
return config;
|
||||
}
|
||||
Log.Info($"Loading config {configPath}");
|
||||
return TorchConfig.LoadFrom(configPath);
|
||||
}
|
||||
|
||||
private static void RunSteamCmd()
|
||||
else
|
||||
{
|
||||
var log = LogManager.GetLogger("SteamCMD");
|
||||
|
||||
if (!Directory.Exists(STEAMCMD_DIR))
|
||||
{
|
||||
Directory.CreateDirectory(STEAMCMD_DIR);
|
||||
}
|
||||
|
||||
if (!File.Exists(RUNSCRIPT_PATH))
|
||||
File.WriteAllText(RUNSCRIPT_PATH, RUNSCRIPT);
|
||||
|
||||
if (!File.Exists(STEAMCMD_PATH))
|
||||
{
|
||||
try
|
||||
{
|
||||
log.Info("Downloading SteamCMD.");
|
||||
using (var client = new WebClient())
|
||||
client.DownloadFile("https://steamcdn-a.akamaihd.net/client/installer/steamcmd.zip", STEAMCMD_ZIP);
|
||||
|
||||
ZipFile.ExtractToDirectory(STEAMCMD_ZIP, STEAMCMD_DIR);
|
||||
File.Delete(STEAMCMD_ZIP);
|
||||
log.Info("SteamCMD downloaded successfully!");
|
||||
}
|
||||
catch
|
||||
{
|
||||
log.Error("Failed to download SteamCMD, unable to update the DS.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
log.Info("Checking for DS updates.");
|
||||
var steamCmdProc = new ProcessStartInfo(STEAMCMD_PATH, "+runscript runscript.txt")
|
||||
{
|
||||
WorkingDirectory = Path.Combine(Directory.GetCurrentDirectory(), STEAMCMD_DIR),
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
StandardOutputEncoding = Encoding.ASCII
|
||||
};
|
||||
var cmd = Process.Start(steamCmdProc);
|
||||
|
||||
// ReSharper disable once PossibleNullReferenceException
|
||||
while (!cmd.HasExited)
|
||||
{
|
||||
log.Info(cmd.StandardOutput.ReadLine());
|
||||
Thread.Sleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
private void LogException(Exception ex)
|
||||
{
|
||||
if (ex.InnerException != null)
|
||||
{
|
||||
LogException(ex.InnerException);
|
||||
}
|
||||
|
||||
Log.Fatal(ex);
|
||||
if (ex is ReflectionTypeLoadException exti)
|
||||
foreach (Exception exl in exti.LoaderExceptions)
|
||||
LogException(exl);
|
||||
}
|
||||
|
||||
private void HandleException(object sender, UnhandledExceptionEventArgs e)
|
||||
{
|
||||
var ex = (Exception)e.ExceptionObject;
|
||||
LogException(ex);
|
||||
Console.WriteLine("Exiting in 5 seconds.");
|
||||
Thread.Sleep(5000);
|
||||
LogManager.Flush();
|
||||
if (_config.RestartOnCrash)
|
||||
{
|
||||
var exe = typeof(Program).Assembly.Location;
|
||||
_config.WaitForPID = Process.GetCurrentProcess().Id.ToString();
|
||||
Process.Start(exe, _config.ToString());
|
||||
}
|
||||
|
||||
Process.GetCurrentProcess().Kill();
|
||||
Log.Info($"Generating default config at {configPath}");
|
||||
var config = new TorchConfig {InstancePath = Path.GetFullPath("Instance")};
|
||||
config.Save(configPath);
|
||||
return config;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void RunSteamCmd()
|
||||
{
|
||||
var log = LogManager.GetLogger("SteamCMD");
|
||||
|
||||
if (!Directory.Exists(STEAMCMD_DIR))
|
||||
{
|
||||
Directory.CreateDirectory(STEAMCMD_DIR);
|
||||
}
|
||||
|
||||
if (!File.Exists(RUNSCRIPT_PATH))
|
||||
File.WriteAllText(RUNSCRIPT_PATH, RUNSCRIPT);
|
||||
|
||||
if (!File.Exists(STEAMCMD_PATH))
|
||||
{
|
||||
try
|
||||
{
|
||||
log.Info("Downloading SteamCMD.");
|
||||
using (var client = new WebClient())
|
||||
client.DownloadFile("https://steamcdn-a.akamaihd.net/client/installer/steamcmd.zip", STEAMCMD_ZIP);
|
||||
|
||||
ZipFile.ExtractToDirectory(STEAMCMD_ZIP, STEAMCMD_DIR);
|
||||
File.Delete(STEAMCMD_ZIP);
|
||||
log.Info("SteamCMD downloaded successfully!");
|
||||
}
|
||||
catch
|
||||
{
|
||||
log.Error("Failed to download SteamCMD, unable to update the DS.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
log.Info("Checking for DS updates.");
|
||||
var steamCmdProc = new ProcessStartInfo(STEAMCMD_PATH, "+runscript runscript.txt")
|
||||
{
|
||||
WorkingDirectory = Path.Combine(Directory.GetCurrentDirectory(), STEAMCMD_DIR),
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
StandardOutputEncoding = Encoding.ASCII
|
||||
};
|
||||
var cmd = Process.Start(steamCmdProc);
|
||||
|
||||
// ReSharper disable once PossibleNullReferenceException
|
||||
while (!cmd.HasExited)
|
||||
{
|
||||
log.Info(cmd.StandardOutput.ReadLine());
|
||||
Thread.Sleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
private void LogException(Exception ex)
|
||||
{
|
||||
if (ex.InnerException != null)
|
||||
{
|
||||
LogException(ex.InnerException);
|
||||
}
|
||||
|
||||
Log.Fatal(ex);
|
||||
if (ex is ReflectionTypeLoadException exti)
|
||||
foreach (Exception exl in exti.LoaderExceptions)
|
||||
LogException(exl);
|
||||
}
|
||||
|
||||
private void HandleException(object sender, UnhandledExceptionEventArgs e)
|
||||
{
|
||||
var ex = (Exception)e.ExceptionObject;
|
||||
LogException(ex);
|
||||
LogManager.Flush();
|
||||
if (_config.RestartOnCrash)
|
||||
{
|
||||
Console.WriteLine("Restarting in 5 seconds.");
|
||||
Thread.Sleep(5000);
|
||||
var exe = typeof(Program).Assembly.Location;
|
||||
_config.WaitForPID = Process.GetCurrentProcess().Id.ToString();
|
||||
Process.Start(exe, _config.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show("Torch encountered a fatal error and needs to close. Please check the logs for details.");
|
||||
}
|
||||
|
||||
Process.GetCurrentProcess().Kill();
|
||||
}
|
||||
}
|
||||
}
|
@@ -10,13 +10,18 @@ using Havok;
|
||||
using NLog;
|
||||
using Sandbox.Engine.Networking;
|
||||
using Sandbox.Engine.Utils;
|
||||
using Sandbox.Game;
|
||||
using Sandbox.Game.Gui;
|
||||
using Torch.API;
|
||||
using Torch.API.Managers;
|
||||
using Torch.Managers;
|
||||
using Torch.Server.ViewModels;
|
||||
using VRage;
|
||||
using VRage.FileSystem;
|
||||
using VRage.Game;
|
||||
using VRage.Game.ObjectBuilder;
|
||||
using VRage.ObjectBuilders;
|
||||
using VRage.Plugins;
|
||||
|
||||
namespace Torch.Server.Managers
|
||||
{
|
||||
@@ -37,6 +42,8 @@ namespace Torch.Server.Managers
|
||||
|
||||
public void LoadInstance(string path, bool validate = true)
|
||||
{
|
||||
Log.Info($"Loading instance {path}");
|
||||
|
||||
if (validate)
|
||||
ValidateInstance(path);
|
||||
|
||||
@@ -56,6 +63,7 @@ namespace Torch.Server.Managers
|
||||
config.Load(configPath);
|
||||
|
||||
DedicatedConfig = new ConfigDedicatedViewModel(config);
|
||||
|
||||
var worldFolders = Directory.EnumerateDirectories(Path.Combine(Torch.Config.InstancePath, "Saves"));
|
||||
|
||||
foreach (var f in worldFolders)
|
||||
|
49
Torch.Server/MultiTextWriter.cs
Normal file
49
Torch.Server/MultiTextWriter.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Torch.Server
|
||||
{
|
||||
public class MultiTextWriter : TextWriter
|
||||
{
|
||||
private IEnumerable<TextWriter> writers;
|
||||
public MultiTextWriter(IEnumerable<TextWriter> writers)
|
||||
{
|
||||
this.writers = writers.ToList();
|
||||
}
|
||||
public MultiTextWriter(params TextWriter[] writers)
|
||||
{
|
||||
this.writers = writers;
|
||||
}
|
||||
|
||||
public override void Write(char value)
|
||||
{
|
||||
foreach (var writer in writers)
|
||||
writer.Write(value);
|
||||
}
|
||||
|
||||
public override void Write(string value)
|
||||
{
|
||||
foreach (var writer in writers)
|
||||
writer.Write(value);
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
foreach (var writer in writers)
|
||||
writer.Flush();
|
||||
}
|
||||
|
||||
public override void Close()
|
||||
{
|
||||
foreach (var writer in writers)
|
||||
writer.Close();
|
||||
}
|
||||
|
||||
public override Encoding Encoding
|
||||
{
|
||||
get { return Encoding.ASCII; }
|
||||
}
|
||||
}
|
||||
}
|
89
Torch.Server/RichTextBoxWriter.cs
Normal file
89
Torch.Server/RichTextBoxWriter.cs
Normal file
@@ -0,0 +1,89 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Torch.Server
|
||||
{
|
||||
public class RichTextBoxWriter : TextWriter
|
||||
{
|
||||
private RichTextBox textbox;
|
||||
private StringBuilder _cache = new StringBuilder();
|
||||
public RichTextBoxWriter(RichTextBox textbox)
|
||||
{
|
||||
this.textbox = textbox;
|
||||
textbox.Document.Background = new SolidColorBrush(UnpackColor(Console.BackgroundColor));
|
||||
textbox.Document.Blocks.Clear();
|
||||
textbox.Document.Blocks.Add(new Paragraph {LineHeight = 12});
|
||||
}
|
||||
|
||||
public override void Write(char value)
|
||||
{
|
||||
if (value == '\r')
|
||||
return;
|
||||
|
||||
_cache.Append(value);
|
||||
if (value == '\n')
|
||||
{
|
||||
var str = _cache.ToString();
|
||||
_cache.Clear();
|
||||
|
||||
var brush = _brushes[Console.ForegroundColor];
|
||||
textbox.Dispatcher.BeginInvoke(() =>
|
||||
{
|
||||
var p = (Paragraph)textbox.Document.Blocks.FirstBlock;
|
||||
p.Inlines.Add(new Run(str) { Foreground = brush });
|
||||
textbox.ScrollToEnd();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override void Write(string value)
|
||||
{
|
||||
var brush = _brushes[Console.ForegroundColor];
|
||||
textbox.Dispatcher.BeginInvoke(() =>
|
||||
{
|
||||
var p = (Paragraph)textbox.Document.Blocks.FirstBlock;
|
||||
p.Inlines.Add(new Run(value) { Foreground = brush });
|
||||
textbox.ScrollToEnd();
|
||||
});
|
||||
}
|
||||
|
||||
public override Encoding Encoding
|
||||
{
|
||||
get { return Encoding.ASCII; }
|
||||
}
|
||||
|
||||
static RichTextBoxWriter()
|
||||
{
|
||||
foreach (var value in (ConsoleColor[])Enum.GetValues(typeof(ConsoleColor)))
|
||||
{
|
||||
_brushes.Add(value, new SolidColorBrush(UnpackColor(value)));
|
||||
}
|
||||
}
|
||||
|
||||
private static Dictionary<ConsoleColor, SolidColorBrush> _brushes = new Dictionary<ConsoleColor, SolidColorBrush>();
|
||||
|
||||
private static Color UnpackColor(ConsoleColor color)
|
||||
{
|
||||
var colorByte = (byte)color;
|
||||
var isBright = (colorByte & 0b1000) >> 3 > 0;
|
||||
var brightness = isBright ? (byte)255 : (byte)128;
|
||||
var red = (colorByte & 0b0100) >> 2;
|
||||
var green = (colorByte & 0b0010) >> 1;
|
||||
var blue = (colorByte & 0b0001);
|
||||
|
||||
return new Color
|
||||
{
|
||||
R = (byte)(brightness * red),
|
||||
G = (byte)(brightness * green),
|
||||
B = (byte)(brightness * blue),
|
||||
A = 255
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@@ -227,6 +227,8 @@
|
||||
</Compile>
|
||||
<Compile Include="Views\Converters\BooleanAndConverter.cs" />
|
||||
<Compile Include="Views\Converters\ListConverter.cs" />
|
||||
<Compile Include="MultiTextWriter.cs" />
|
||||
<Compile Include="RichTextBoxWriter.cs" />
|
||||
<Compile Include="Views\ValidationRules\ListConverterValidationRule.cs" />
|
||||
<Compile Include="Views\Entities\EntityControlHost.xaml.cs">
|
||||
<DependentUpon>EntityControlHost.xaml</DependentUpon>
|
||||
|
@@ -70,6 +70,11 @@ namespace Torch.Server
|
||||
}
|
||||
}
|
||||
|
||||
private bool _canRun;
|
||||
public bool CanRun { get => _canRun; set => SetValue(ref _canRun, value); }
|
||||
|
||||
private bool _hasRun;
|
||||
|
||||
/// <inheritdoc />
|
||||
public InstanceManager DedicatedInstance { get; }
|
||||
|
||||
@@ -107,12 +112,13 @@ namespace Torch.Server
|
||||
/// <inheritdoc />
|
||||
public override void Init()
|
||||
{
|
||||
Log.Info($"Init server '{Config.InstanceName}' at '{Config.InstancePath}'");
|
||||
Sandbox.Engine.Platform.Game.IsDedicated = true;
|
||||
|
||||
base.Init();
|
||||
Log.Info($"Init server '{Config.InstanceName}' at '{Config.InstancePath}'");
|
||||
|
||||
Managers.GetManager<ITorchSessionManager>().SessionStateChanged += OnSessionStateChanged;
|
||||
GetManager<InstanceManager>().LoadInstance(Config.InstancePath);
|
||||
CanRun = true;
|
||||
}
|
||||
|
||||
private void OnSessionStateChanged(ITorchSession session, TorchSessionState newState)
|
||||
@@ -129,8 +135,17 @@ namespace Torch.Server
|
||||
{
|
||||
if (State != ServerState.Stopped)
|
||||
return;
|
||||
|
||||
if (_hasRun)
|
||||
{
|
||||
Restart();
|
||||
return;
|
||||
}
|
||||
|
||||
State = ServerState.Starting;
|
||||
IsRunning = true;
|
||||
CanRun = false;
|
||||
_hasRun = true;
|
||||
Log.Info("Starting server.");
|
||||
MySandboxGame.ConfigDedicated = DedicatedInstance.DedicatedConfig.Model;
|
||||
|
||||
@@ -150,6 +165,7 @@ namespace Torch.Server
|
||||
|
||||
State = ServerState.Stopped;
|
||||
IsRunning = false;
|
||||
CanRun = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -157,12 +173,17 @@ namespace Torch.Server
|
||||
/// </summary>
|
||||
public override void Restart()
|
||||
{
|
||||
Save().ContinueWith((task, torchO) =>
|
||||
if (IsRunning)
|
||||
Save().ContinueWith(DoRestart, this, TaskContinuationOptions.RunContinuationsAsynchronously);
|
||||
else
|
||||
DoRestart(null, this);
|
||||
|
||||
void DoRestart(Task<GameSaveResult> task, object torch0)
|
||||
{
|
||||
var torch = (TorchServer) torchO;
|
||||
var torch = (TorchServer)torch0;
|
||||
torch.Stop();
|
||||
// TODO clone this
|
||||
var config = (TorchConfig) torch.Config;
|
||||
var config = (TorchConfig)torch.Config;
|
||||
LogManager.Flush();
|
||||
|
||||
string exe = Assembly.GetExecutingAssembly().Location;
|
||||
@@ -172,7 +193,7 @@ namespace Torch.Server
|
||||
Process.Start(exe, config.ToString());
|
||||
|
||||
Process.GetCurrentProcess().Kill();
|
||||
}, this, TaskContinuationOptions.RunContinuationsAsynchronously);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
@@ -28,22 +28,18 @@
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition/>
|
||||
</Grid.RowDefinitions>
|
||||
<Menu Grid.Row="0">
|
||||
<MenuItem Header="File"/>
|
||||
<MenuItem Header="Tools"/>
|
||||
</Menu>
|
||||
<StackPanel Grid.Row="1" Margin="5,5,5,5" Orientation="Horizontal">
|
||||
<Button x:Name="BtnStart" Content="Start" Height="24" Width="75" Margin="5,0,5,0"
|
||||
HorizontalAlignment="Left" Click="BtnStart_Click">
|
||||
HorizontalAlignment="Left" Click="BtnStart_Click" Background="LightGreen">
|
||||
<Button.IsEnabled>
|
||||
<MultiBinding Converter="{StaticResource BooleanAndConverter}">
|
||||
<Binding ElementName="MainWindow" Path="DataContext.IsRunning" Converter="{StaticResource InverseBool}"/>
|
||||
<Binding ElementName="MainWindow" Path="DataContext.CanRun"/>
|
||||
<Binding ElementName="ConfigControl" Path="ConfigValid"/>
|
||||
</MultiBinding>
|
||||
</Button.IsEnabled>
|
||||
</Button>
|
||||
<Button x:Name="BtnStop" Content="Stop" Height="24" Width="75" Margin="5,0,5,0" HorizontalAlignment="Left"
|
||||
Click="BtnStop_Click" IsEnabled="{Binding IsRunning}" />
|
||||
Click="BtnStop_Click" IsEnabled="{Binding IsRunning}" Background="IndianRed"/>
|
||||
<Label>
|
||||
<Label.Content>
|
||||
<TextBlock Text="{Binding State, StringFormat=Status: {0}}"></TextBlock>
|
||||
@@ -60,7 +56,10 @@
|
||||
</Label.Content>
|
||||
</Label>
|
||||
</StackPanel>
|
||||
<TabControl Grid.Row="2" Height="Auto" x:Name="TabControl" Margin="5,0,5,5">
|
||||
<TabControl Grid.Row="2" Height="Auto" x:Name="TabControl" Margin="5,10,5,5">
|
||||
<TabItem Header="Console">
|
||||
<RichTextBox x:Name="ConsoleText" VerticalScrollBarVisibility="Visible" FontFamily="Consolas"/>
|
||||
</TabItem>
|
||||
<TabItem Header="Configuration">
|
||||
<Grid IsEnabled="{Binding IsRunning, Converter={StaticResource InverseBool}}">
|
||||
<Grid.RowDefinitions>
|
||||
|
@@ -1,25 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
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;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
using Sandbox;
|
||||
using Torch.API;
|
||||
using Torch.Server.Managers;
|
||||
using MessageBoxResult = System.Windows.MessageBoxResult;
|
||||
using Timer = System.Timers.Timer;
|
||||
|
||||
namespace Torch.Server
|
||||
@@ -49,6 +45,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));
|
||||
}
|
||||
|
||||
public void LoadConfig(TorchConfig config)
|
||||
@@ -65,12 +68,15 @@ namespace Torch.Server
|
||||
|
||||
private void BtnStart_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_server.Start();
|
||||
Task.Run(() => _server.Start());
|
||||
}
|
||||
|
||||
private void BtnStop_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_server.Stop();
|
||||
var result = MessageBox.Show("Are you sure you want to stop the server?", "Stop Server", MessageBoxButton.YesNo);
|
||||
|
||||
if (result == MessageBoxResult.Yes)
|
||||
_server.Invoke(() => _server.Stop());
|
||||
}
|
||||
|
||||
protected override void OnClosing(CancelEventArgs e)
|
||||
@@ -82,6 +88,8 @@ namespace Torch.Server
|
||||
|
||||
if (_server?.State == ServerState.Running)
|
||||
_server.Stop();
|
||||
|
||||
Environment.Exit(0);
|
||||
}
|
||||
|
||||
private void BtnRestart_Click(object sender, RoutedEventArgs e)
|
||||
|
@@ -3,6 +3,7 @@ using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@@ -26,6 +27,7 @@ using VRage;
|
||||
using VRage.Audio;
|
||||
using VRage.FileSystem;
|
||||
using VRage.Game;
|
||||
using VRage.Game.ObjectBuilder;
|
||||
using VRage.Game.SessionComponents;
|
||||
using VRage.GameServices;
|
||||
using VRage.Network;
|
||||
@@ -200,10 +202,16 @@ namespace Torch
|
||||
MyRenderProxy.GetRenderProfiler().InitMemoryHack("MainEntryPoint");
|
||||
}
|
||||
|
||||
// var layers = _layerSettings();
|
||||
// layers[layers.Length - 1].Radius *= 4;
|
||||
|
||||
_game = new SpaceEngineersGame(_runArgs);
|
||||
// Loads object builder serializers. Intuitive, right?
|
||||
_log.Info("Setting up serializers");
|
||||
MyPlugins.RegisterGameAssemblyFile(MyPerGameSettings.GameModAssembly);
|
||||
if (MyPerGameSettings.GameModBaseObjBuildersAssembly != null)
|
||||
MyPlugins.RegisterBaseGameObjectBuildersAssemblyFile(MyPerGameSettings.GameModBaseObjBuildersAssembly);
|
||||
MyPlugins.RegisterGameObjectBuildersAssemblyFile(MyPerGameSettings.GameModObjBuildersAssembly);
|
||||
MyPlugins.RegisterSandboxAssemblyFile(MyPerGameSettings.SandboxAssembly);
|
||||
MyPlugins.RegisterSandboxGameAssemblyFile(MyPerGameSettings.SandboxGameAssembly);
|
||||
//typeof(MySandboxGame).GetMethod("Preallocate", BindingFlags.Static | BindingFlags.NonPublic).Invoke(null, null);
|
||||
MyGlobalTypeMetadata.Static.Init(false);
|
||||
}
|
||||
|
||||
private void Destroy()
|
||||
@@ -220,6 +228,8 @@ namespace Torch
|
||||
|
||||
private void DoStart()
|
||||
{
|
||||
_game = new SpaceEngineersGame(_runArgs);
|
||||
|
||||
if (MySandboxGame.FatalErrorDuringInit)
|
||||
{
|
||||
_log.Warn("Failed to start sandbox game: fatal error during init");
|
||||
|
@@ -52,13 +52,12 @@ namespace Torch
|
||||
/// <summary>
|
||||
/// Assign a value to the given field and raise PropertyChanged for the caller.
|
||||
/// </summary>
|
||||
protected virtual void SetValue<T>(ref T backingField, T value, [CallerMemberName] string propName = "")
|
||||
protected virtual void SetValue<T>(ref T field, T value, [CallerMemberName] string propName = "")
|
||||
{
|
||||
if (backingField != null && backingField.Equals(value))
|
||||
if (EqualityComparer<T>.Default.Equals(field, value))
|
||||
return;
|
||||
|
||||
backingField = value;
|
||||
// ReSharper disable once ExplicitCallerInfoArgument
|
||||
field = value;
|
||||
OnPropertyChanged(propName);
|
||||
}
|
||||
|
||||
@@ -71,7 +70,6 @@ namespace Torch
|
||||
throw new ArgumentNullException(nameof(setter));
|
||||
|
||||
setter.Invoke(value);
|
||||
// ReSharper disable once ExplicitCallerInfoArgument
|
||||
OnPropertyChanged(propName);
|
||||
}
|
||||
|
||||
@@ -80,9 +78,8 @@ namespace Torch
|
||||
/// </summary>
|
||||
public void RefreshModel()
|
||||
{
|
||||
foreach (var propName in GetType().GetProperties().Select(x => x.Name))
|
||||
// ReSharper disable once ExplicitCallerInfoArgument
|
||||
OnPropertyChanged(propName);
|
||||
foreach (var property in GetType().GetProperties())
|
||||
OnPropertyChanged(property.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user