Merge branch 'master' into Patron
This commit is contained in:
@@ -17,6 +17,6 @@ if (!(Test-Path $steamCMDPath)) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cd "$steamData"
|
cd "$steamData"
|
||||||
& "$steamCMDPath/steamcmd.exe" "+login anonymous" "+force_install_dir $steamData" "+app_update 298740 -beta publictest -betapassword nt8WuDw9kdvE validate" "+quit"
|
& "$steamCMDPath/steamcmd.exe" "+login anonymous" "+force_install_dir $steamData" "+app_update 298740 validate" "+quit"
|
||||||
|
|
||||||
popd
|
popd
|
||||||
|
@@ -254,6 +254,7 @@ quit";
|
|||||||
|
|
||||||
private void HandleException(object sender, UnhandledExceptionEventArgs e)
|
private void HandleException(object sender, UnhandledExceptionEventArgs e)
|
||||||
{
|
{
|
||||||
|
_server.FatalException = true;
|
||||||
var ex = (Exception)e.ExceptionObject;
|
var ex = (Exception)e.ExceptionObject;
|
||||||
LogException(ex);
|
LogException(ex);
|
||||||
if (MyFakes.ENABLE_MINIDUMP_SENDING)
|
if (MyFakes.ENABLE_MINIDUMP_SENDING)
|
||||||
|
@@ -63,7 +63,7 @@ namespace Torch.Server
|
|||||||
// Breaks on Windows Server 2019
|
// Breaks on Windows Server 2019
|
||||||
if (!new ComputerInfo().OSFullName.Contains("Server 2019") && !Environment.UserInteractive)
|
if (!new ComputerInfo().OSFullName.Contains("Server 2019") && !Environment.UserInteractive)
|
||||||
{
|
{
|
||||||
using (var service = new TorchService())
|
using (var service = new TorchService(args))
|
||||||
ServiceBase.Run(service);
|
ServiceBase.Run(service);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@@ -49,6 +49,8 @@ namespace Torch.Server
|
|||||||
private Timer _watchdog;
|
private Timer _watchdog;
|
||||||
private int _players;
|
private int _players;
|
||||||
private MultiplayerManagerDedicated _multiplayerManagerDedicated;
|
private MultiplayerManagerDedicated _multiplayerManagerDedicated;
|
||||||
|
|
||||||
|
internal bool FatalException { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public TorchServer(TorchConfig config = null)
|
public TorchServer(TorchConfig config = null)
|
||||||
@@ -232,10 +234,16 @@ namespace Torch.Server
|
|||||||
|
|
||||||
private static void CheckServerResponding(object state)
|
private static void CheckServerResponding(object state)
|
||||||
{
|
{
|
||||||
|
var server = (TorchServer)state;
|
||||||
var mre = new ManualResetEvent(false);
|
var mre = new ManualResetEvent(false);
|
||||||
((TorchServer)state).Invoke(() => mre.Set());
|
server.Invoke(() => mre.Set());
|
||||||
if (!mre.WaitOne(TimeSpan.FromSeconds(Instance.Config.TickTimeout)))
|
if (!mre.WaitOne(TimeSpan.FromSeconds(Instance.Config.TickTimeout)))
|
||||||
{
|
{
|
||||||
|
if (server.FatalException)
|
||||||
|
{
|
||||||
|
server._watchdog.Dispose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
Log.Error(
|
Log.Error(
|
||||||
$"Server watchdog detected that the server was frozen for at least {((TorchServer) state).Config.TickTimeout} seconds.");
|
$"Server watchdog detected that the server was frozen for at least {((TorchServer) state).Config.TickTimeout} seconds.");
|
||||||
|
@@ -1,10 +1,12 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.ServiceProcess;
|
using System.ServiceProcess;
|
||||||
|
using System.Threading;
|
||||||
using NLog;
|
using NLog;
|
||||||
using Torch.API;
|
using Torch.API;
|
||||||
|
|
||||||
@@ -12,12 +14,14 @@ namespace Torch.Server
|
|||||||
{
|
{
|
||||||
class TorchService : ServiceBase
|
class TorchService : ServiceBase
|
||||||
{
|
{
|
||||||
|
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
|
||||||
public const string Name = "Torch (SEDS)";
|
public const string Name = "Torch (SEDS)";
|
||||||
private TorchServer _server;
|
|
||||||
private Initializer _initializer;
|
private Initializer _initializer;
|
||||||
|
private string[] _args;
|
||||||
|
|
||||||
public TorchService()
|
public TorchService(string[] args)
|
||||||
{
|
{
|
||||||
|
_args = args;
|
||||||
var workingDir = new FileInfo(typeof(TorchService).Assembly.Location).Directory.ToString();
|
var workingDir = new FileInfo(typeof(TorchService).Assembly.Location).Directory.ToString();
|
||||||
Directory.SetCurrentDirectory(workingDir);
|
Directory.SetCurrentDirectory(workingDir);
|
||||||
_initializer = new Initializer(workingDir);
|
_initializer = new Initializer(workingDir);
|
||||||
@@ -29,19 +33,21 @@ namespace Torch.Server
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void OnStart(string[] args)
|
protected override void OnStart(string[] _)
|
||||||
{
|
{
|
||||||
base.OnStart(args);
|
base.OnStart(_args);
|
||||||
|
|
||||||
_initializer.Initialize(args);
|
_initializer.Initialize(_args);
|
||||||
_initializer.Run();
|
_initializer.Run();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void OnStop()
|
protected override void OnStop()
|
||||||
{
|
{
|
||||||
_server.Stop();
|
var mre = new ManualResetEvent(false);
|
||||||
base.OnStop();
|
Task.Run(() => _initializer.Server.Stop());
|
||||||
|
if (!mre.WaitOne(TimeSpan.FromMinutes(1)))
|
||||||
|
Process.GetCurrentProcess().Kill();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -29,6 +29,8 @@ namespace Torch.Commands
|
|||||||
{
|
{
|
||||||
private static bool _restartPending = false;
|
private static bool _restartPending = false;
|
||||||
private static bool _cancelRestart = false;
|
private static bool _cancelRestart = false;
|
||||||
|
private bool _stopPending = false;
|
||||||
|
private bool _cancelStop = false;
|
||||||
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
|
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
[Command("whatsmyip")]
|
[Command("whatsmyip")]
|
||||||
@@ -154,9 +156,25 @@ namespace Torch.Commands
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Command("stop", "Stops the server.")]
|
[Command("stop", "Stops the server.")]
|
||||||
public void Stop(bool save = true)
|
public void Stop(bool save = true, int countdownSeconds = 0)
|
||||||
{
|
{
|
||||||
Context.Respond("Stopping server.");
|
if (_stopPending)
|
||||||
|
{
|
||||||
|
Context.Respond("A stop is already pending.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_stopPending = true;
|
||||||
|
Task.Run(() =>
|
||||||
|
{
|
||||||
|
var countdown = StopCountdown(countdownSeconds, save).GetEnumerator();
|
||||||
|
while (countdown.MoveNext())
|
||||||
|
{
|
||||||
|
Thread.Sleep(1000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/*Context.Respond("Stopping server.");
|
||||||
if (save)
|
if (save)
|
||||||
DoSave()?.ContinueWith((a, mod) =>
|
DoSave()?.ContinueWith((a, mod) =>
|
||||||
{
|
{
|
||||||
@@ -165,7 +183,7 @@ namespace Torch.Commands
|
|||||||
torch.Stop();
|
torch.Stop();
|
||||||
}, this, TaskContinuationOptions.RunContinuationsAsynchronously);
|
}, this, TaskContinuationOptions.RunContinuationsAsynchronously);
|
||||||
else
|
else
|
||||||
Context.Torch.Stop();
|
Context.Torch.Stop();*/
|
||||||
}
|
}
|
||||||
|
|
||||||
[Command("restart", "Restarts the server.")]
|
[Command("restart", "Restarts the server.")]
|
||||||
@@ -204,6 +222,69 @@ namespace Torch.Commands
|
|||||||
else
|
else
|
||||||
Context.Respond("A restart is not pending.");
|
Context.Respond("A restart is not pending.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Command("stop cancel", "Cancel a pending stop.")]
|
||||||
|
public void CancelStop()
|
||||||
|
{
|
||||||
|
if (_restartPending)
|
||||||
|
_cancelStop = true;
|
||||||
|
else
|
||||||
|
Context.Respond("Server Stop is not pending.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable StopCountdown(int countdown, bool save)
|
||||||
|
{
|
||||||
|
for (var i = countdown; i >= 0; i--)
|
||||||
|
{
|
||||||
|
if (_cancelStop)
|
||||||
|
{
|
||||||
|
Context.Torch.CurrentSession.Managers.GetManager<IChatManagerClient>()
|
||||||
|
.SendMessageAsSelf($"Stop cancelled.");
|
||||||
|
|
||||||
|
_stopPending = false;
|
||||||
|
_cancelStop = false;
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i >= 60 && i % 60 == 0)
|
||||||
|
{
|
||||||
|
Context.Torch.CurrentSession.Managers.GetManager<IChatManagerClient>()
|
||||||
|
.SendMessageAsSelf($"Stopping server in {i / 60} minute{Pluralize(i / 60)}.");
|
||||||
|
yield return null;
|
||||||
|
}
|
||||||
|
else if (i > 0)
|
||||||
|
{
|
||||||
|
if (i < 11)
|
||||||
|
Context.Torch.CurrentSession.Managers.GetManager<IChatManagerClient>()
|
||||||
|
.SendMessageAsSelf($"Stopping server in {i} second{Pluralize(i)}.");
|
||||||
|
yield return null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (save)
|
||||||
|
{
|
||||||
|
Log.Info("Saving game before stop.");
|
||||||
|
Context.Torch.CurrentSession.Managers.GetManager<IChatManagerClient>()
|
||||||
|
.SendMessageAsSelf($"Saving game before stop.");
|
||||||
|
DoSave()?.ContinueWith((a, mod) =>
|
||||||
|
{
|
||||||
|
ITorchBase torch = (mod as CommandModule)?.Context?.Torch;
|
||||||
|
Debug.Assert(torch != null);
|
||||||
|
torch.Stop();
|
||||||
|
}, this, TaskContinuationOptions.RunContinuationsAsynchronously);
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log.Info("Stopping server.");
|
||||||
|
Context.Torch.Invoke(() => Context.Torch.Stop());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private IEnumerable RestartCountdown(int countdown, bool save)
|
private IEnumerable RestartCountdown(int countdown, bool save)
|
||||||
{
|
{
|
||||||
|
@@ -199,7 +199,8 @@ namespace Torch
|
|||||||
}
|
}
|
||||||
MyRenderProxy.Initialize(renderer);
|
MyRenderProxy.Initialize(renderer);
|
||||||
MyRenderProfiler.SetAutocommit(false);
|
MyRenderProfiler.SetAutocommit(false);
|
||||||
MyRenderProfiler.InitMemoryHack("MainEntryPoint");
|
//This broke services?
|
||||||
|
//MyRenderProfiler.InitMemoryHack("MainEntryPoint");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loads object builder serializers. Intuitive, right?
|
// Loads object builder serializers. Intuitive, right?
|
||||||
|
Reference in New Issue
Block a user