Compare commits
6 Commits
1.1.207.7
...
1.1.229.26
Author | SHA1 | Date | |
---|---|---|---|
![]() |
82815f66e5 | ||
![]() |
97da740e7e | ||
![]() |
42bb24ca6a | ||
![]() |
2f3b6cdda7 | ||
![]() |
525b496774 | ||
![]() |
562bb77dda |
11
CHANGELOG.md
11
CHANGELOG.md
@@ -1,4 +1,13 @@
|
|||||||
# Torch 1.1.205.478
|
# Torch 1.1.229.265
|
||||||
|
* Features
|
||||||
|
- Added more lenient version parsing for plugins (v#.# should work)
|
||||||
|
- Added countdown option to restart command (!restart [seconds])
|
||||||
|
* Fixes
|
||||||
|
- General fixes to work with the latest SE version
|
||||||
|
- Fixed config changes not saving
|
||||||
|
- (hopefully) Fixed issue causing crashes on servers using the Windows Classic theme
|
||||||
|
|
||||||
|
# Torch 1.1.207.7
|
||||||
* Notes
|
* Notes
|
||||||
- This release makes significant changes to TorchConfig.xml. It has been renamed to Torch.cfg and has different options.
|
- This release makes significant changes to TorchConfig.xml. It has been renamed to Torch.cfg and has different options.
|
||||||
* Features
|
* Features
|
||||||
|
17
README.md
17
README.md
@@ -10,17 +10,15 @@ Torch is the successor to SE Server Extender and gives server admins the tools t
|
|||||||
* Organized, easy to use configuration editor
|
* Organized, easy to use configuration editor
|
||||||
* Extensible using the Torch plugin system
|
* Extensible using the Torch plugin system
|
||||||
|
|
||||||
|
# Installation
|
||||||
|
|
||||||
|
* Get the latest Torch release here: https://github.com/TorchAPI/Torch/releases
|
||||||
|
* Unzip the Torch release into its own directory and run the executable. It will automatically download the SE DS and generate the other necessary files.
|
||||||
|
- If you already have a DS installed you can unzip the Torch files into the folder that contains the DedicatedServer64 folder.
|
||||||
|
|
||||||
# Building
|
# Building
|
||||||
To build Torch you must first have a complete SE Dedicated installation somewhere. Before you open the solution, run the Setup batch file and enter the path of that installation's DedicatedServer64 folder. The script will make a symlink to that folder so the Torch solution can find the DLL references it needs.
|
To build Torch you must first have a complete SE Dedicated installation somewhere. Before you open the solution, run the Setup batch file and enter the path of that installation's DedicatedServer64 folder. The script will make a symlink to that folder so the Torch solution can find the DLL references it needs.
|
||||||
|
|
||||||
# Installation Guide
|
|
||||||
|
|
||||||
### Automatic (recommended)
|
|
||||||
* Unzip Torch to its own folder, run Torch.Server.exe and enter 'y' in the prompt for automatic updates. Torch will automatically download the Space Engineers files and generate all of the configs/folders necessary.
|
|
||||||
|
|
||||||
### Manual (for hosting companies or the paranoid)
|
|
||||||
* Install the Space Engineers DS and then unzip the Torch files into the server's DedicatedServer64 directory. It will automatically detect the manual install and disable automatic updates.
|
|
||||||
|
|
||||||
In both cases you will need to set the InstancePath in TorchConfig.xml to an existing dedicated server instance as Torch can't fully generate it on its own yet.
|
In both cases you will need to set the InstancePath in TorchConfig.xml to an existing dedicated server instance as Torch can't fully generate it on its own yet.
|
||||||
|
|
||||||
# Official Plugins
|
# Official Plugins
|
||||||
@@ -28,4 +26,5 @@ Install plugins by unzipping them into the 'Plugins' folder which should be in t
|
|||||||
* [Essentials](https://github.com/TorchAPI/Essentials): Adds a slew of chat commands and other tools to help manage your server.
|
* [Essentials](https://github.com/TorchAPI/Essentials): Adds a slew of chat commands and other tools to help manage your server.
|
||||||
* [Concealment](https://github.com/TorchAPI/Concealment): Adds game logic and physics optimizations that significantly improve sim speed.
|
* [Concealment](https://github.com/TorchAPI/Concealment): Adds game logic and physics optimizations that significantly improve sim speed.
|
||||||
|
|
||||||
If you have a more enjoyable server experience because of Torch, please consider supporting us on [Patreon](https://www.patreon.com/bePatron?u=847269)!
|
If you have a more enjoyable server experience because of Torch, please consider supporting us on Patreon.
|
||||||
|
[](https://www.patreon.com/bePatron?u=847269)!
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
[assembly: AssemblyVersion("1.0.207.7")]
|
[assembly: AssemblyVersion("1.0.229.265")]
|
||||||
[assembly: AssemblyFileVersion("1.0.207.7")]
|
[assembly: AssemblyFileVersion("1.0.229.265")]
|
@@ -103,6 +103,9 @@
|
|||||||
<HintPath>..\GameBinaries\VRage.Render11.dll</HintPath>
|
<HintPath>..\GameBinaries\VRage.Render11.dll</HintPath>
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="VRage.Steam">
|
||||||
|
<HintPath>..\..\..\..\..\..\..\steamcmd\steamapps\common\SpaceEngineersDedicatedServer\DedicatedServer64\VRage.Steam.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="WindowsBase" />
|
<Reference Include="WindowsBase" />
|
||||||
<Reference Include="PresentationCore" />
|
<Reference Include="PresentationCore" />
|
||||||
<Reference Include="PresentationFramework" />
|
<Reference Include="PresentationFramework" />
|
||||||
|
@@ -11,6 +11,7 @@ using Sandbox.Engine.Utils;
|
|||||||
using Sandbox.Game;
|
using Sandbox.Game;
|
||||||
using Sandbox.ModAPI;
|
using Sandbox.ModAPI;
|
||||||
using SpaceEngineers.Game;
|
using SpaceEngineers.Game;
|
||||||
|
using VRage.Steam;
|
||||||
using Torch.API;
|
using Torch.API;
|
||||||
using VRage.FileSystem;
|
using VRage.FileSystem;
|
||||||
using VRageRender;
|
using VRageRender;
|
||||||
@@ -22,7 +23,6 @@ namespace Torch.Client
|
|||||||
private MyCommonProgramStartup _startup;
|
private MyCommonProgramStartup _startup;
|
||||||
private IMyRender _renderer;
|
private IMyRender _renderer;
|
||||||
private const uint APP_ID = 244850;
|
private const uint APP_ID = 244850;
|
||||||
private VRageGameServices _services;
|
|
||||||
|
|
||||||
public override void Init()
|
public override void Init()
|
||||||
{
|
{
|
||||||
@@ -59,7 +59,6 @@ namespace Torch.Client
|
|||||||
|
|
||||||
InitializeRender();
|
InitializeRender();
|
||||||
|
|
||||||
_services = new VRageGameServices(mySteamService);
|
|
||||||
if (!Game.IsDedicated)
|
if (!Game.IsDedicated)
|
||||||
MyFileSystem.InitUserSpecific(mySteamService.UserId.ToString());
|
MyFileSystem.InitUserSpecific(mySteamService.UserId.ToString());
|
||||||
}
|
}
|
||||||
@@ -85,7 +84,7 @@ namespace Torch.Client
|
|||||||
|
|
||||||
public override void Start()
|
public override void Start()
|
||||||
{
|
{
|
||||||
using (var spaceEngineersGame = new SpaceEngineersGame(_services, RunArgs))
|
using (var spaceEngineersGame = new SpaceEngineersGame(RunArgs))
|
||||||
{
|
{
|
||||||
Log.Info("Starting client");
|
Log.Info("Starting client");
|
||||||
spaceEngineersGame.OnGameLoaded += SpaceEngineersGame_OnGameLoaded;
|
spaceEngineersGame.OnGameLoaded += SpaceEngineersGame_OnGameLoaded;
|
||||||
|
59
Torch.Server/ListBoxExtensions.cs
Normal file
59
Torch.Server/ListBoxExtensions.cs
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
using System;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Controls.Primitives;
|
||||||
|
using System.Windows.Media;
|
||||||
|
|
||||||
|
namespace Torch.Server
|
||||||
|
{
|
||||||
|
public static class ListBoxExtensions
|
||||||
|
{
|
||||||
|
//https://stackoverflow.com/questions/28689125/how-to-autoscroll-listbox-to-bottom-wpf-c
|
||||||
|
public static void ScrollToItem(this ListBox listBox, int index)
|
||||||
|
{
|
||||||
|
// Find a container
|
||||||
|
UIElement container = null;
|
||||||
|
for (int i = index; i > 0; i--)
|
||||||
|
{
|
||||||
|
container = listBox.ItemContainerGenerator.ContainerFromIndex(i) as UIElement;
|
||||||
|
if (container != null)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (container == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Find the ScrollContentPresenter
|
||||||
|
ScrollContentPresenter presenter = null;
|
||||||
|
for (Visual vis = container; vis != null && vis != listBox; vis = VisualTreeHelper.GetParent(vis) as Visual)
|
||||||
|
if ((presenter = vis as ScrollContentPresenter) != null)
|
||||||
|
break;
|
||||||
|
if (presenter == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Find the IScrollInfo
|
||||||
|
var scrollInfo =
|
||||||
|
!presenter.CanContentScroll ? presenter :
|
||||||
|
presenter.Content as IScrollInfo ??
|
||||||
|
FirstVisualChild(presenter.Content as ItemsPresenter) as IScrollInfo ??
|
||||||
|
presenter;
|
||||||
|
|
||||||
|
// Find the amount of items that is "Visible" in the ListBox
|
||||||
|
var height = (container as ListBoxItem).ActualHeight;
|
||||||
|
var lbHeight = listBox.ActualHeight;
|
||||||
|
var showCount = (int)Math.Floor(lbHeight / height) - 1;
|
||||||
|
|
||||||
|
//Set the scrollbar
|
||||||
|
if (scrollInfo.CanVerticallyScroll)
|
||||||
|
scrollInfo.SetVerticalOffset(index - showCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DependencyObject FirstVisualChild(Visual visual)
|
||||||
|
{
|
||||||
|
if (visual == null) return null;
|
||||||
|
if (VisualTreeHelper.GetChildrenCount(visual) == 0) return null;
|
||||||
|
return VisualTreeHelper.GetChild(visual, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -34,7 +34,10 @@ namespace Torch.Server.Managers
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void Init()
|
public override void Init()
|
||||||
{
|
{
|
||||||
LoadInstance(Torch.Config.InstancePath);
|
MyFileSystem.ExePath = Path.Combine(Torch.GetManager<FilesystemManager>().TorchDirectory, "DedicatedServer64");
|
||||||
|
MyFileSystem.Init("Content", Torch.Config.InstancePath);
|
||||||
|
//Initializes saves path. Why this isn't in Init() we may never know.
|
||||||
|
MyFileSystem.InitUserSpecific(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LoadInstance(string path, bool validate = true)
|
public void LoadInstance(string path, bool validate = true)
|
||||||
@@ -45,6 +48,8 @@ namespace Torch.Server.Managers
|
|||||||
MyFileSystem.Reset();
|
MyFileSystem.Reset();
|
||||||
MyFileSystem.ExePath = Path.Combine(Torch.GetManager<FilesystemManager>().TorchDirectory, "DedicatedServer64");
|
MyFileSystem.ExePath = Path.Combine(Torch.GetManager<FilesystemManager>().TorchDirectory, "DedicatedServer64");
|
||||||
MyFileSystem.Init("Content", path);
|
MyFileSystem.Init("Content", path);
|
||||||
|
//Initializes saves path. Why this isn't in Init() we may never know.
|
||||||
|
MyFileSystem.InitUserSpecific(null);
|
||||||
|
|
||||||
var configPath = Path.Combine(path, CONFIG_NAME);
|
var configPath = Path.Combine(path, CONFIG_NAME);
|
||||||
if (!File.Exists(configPath))
|
if (!File.Exists(configPath))
|
||||||
@@ -68,6 +73,8 @@ namespace Torch.Server.Managers
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImportWorldConfig();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if (string.IsNullOrEmpty(DedicatedConfig.LoadWorld))
|
if (string.IsNullOrEmpty(DedicatedConfig.LoadWorld))
|
||||||
{
|
{
|
||||||
@@ -79,13 +86,13 @@ namespace Torch.Server.Managers
|
|||||||
public void SelectWorld(string worldPath, bool modsOnly = true)
|
public void SelectWorld(string worldPath, bool modsOnly = true)
|
||||||
{
|
{
|
||||||
DedicatedConfig.LoadWorld = worldPath;
|
DedicatedConfig.LoadWorld = worldPath;
|
||||||
LoadWorldMods(modsOnly);
|
ImportWorldConfig(modsOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void LoadWorldMods(bool modsOnly = true)
|
private void ImportWorldConfig(bool modsOnly = true)
|
||||||
{
|
{
|
||||||
if (DedicatedConfig.LoadWorld == null)
|
if (string.IsNullOrEmpty(DedicatedConfig.LoadWorld))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var sandboxPath = Path.Combine(DedicatedConfig.LoadWorld, "Sandbox.sbc");
|
var sandboxPath = Path.Combine(DedicatedConfig.LoadWorld, "Sandbox.sbc");
|
||||||
@@ -93,6 +100,8 @@ namespace Torch.Server.Managers
|
|||||||
if (!File.Exists(sandboxPath))
|
if (!File.Exists(sandboxPath))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
MyObjectBuilderSerializer.DeserializeXML(sandboxPath, out MyObjectBuilder_Checkpoint checkpoint, out ulong sizeInBytes);
|
MyObjectBuilderSerializer.DeserializeXML(sandboxPath, out MyObjectBuilder_Checkpoint checkpoint, out ulong sizeInBytes);
|
||||||
if (checkpoint == null)
|
if (checkpoint == null)
|
||||||
{
|
{
|
||||||
@@ -106,15 +115,21 @@ namespace Torch.Server.Managers
|
|||||||
|
|
||||||
DedicatedConfig.Mods = sb.ToString();
|
DedicatedConfig.Mods = sb.ToString();
|
||||||
|
|
||||||
Log.Info("Loaded mod list from world");
|
Log.Debug("Loaded mod list from world");
|
||||||
|
|
||||||
if (!modsOnly)
|
if (!modsOnly)
|
||||||
DedicatedConfig.SessionSettings = new SessionSettingsViewModel(checkpoint.Settings);
|
DedicatedConfig.SessionSettings = new SessionSettingsViewModel(checkpoint.Settings);
|
||||||
}
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Error($"Error loading mod list from world, verify that your mod list is accurate. '{DedicatedConfig.LoadWorld}'.");
|
||||||
|
Log.Error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void SaveConfig()
|
public void SaveConfig()
|
||||||
{
|
{
|
||||||
DedicatedConfig.Model.Save();
|
DedicatedConfig.Save();
|
||||||
Log.Info("Saved dedicated config.");
|
Log.Info("Saved dedicated config.");
|
||||||
|
|
||||||
try
|
try
|
||||||
|
@@ -84,10 +84,14 @@ namespace Torch.Server
|
|||||||
{
|
{
|
||||||
var pid = int.Parse(_config.WaitForPID);
|
var pid = int.Parse(_config.WaitForPID);
|
||||||
var waitProc = Process.GetProcessById(pid);
|
var waitProc = Process.GetProcessById(pid);
|
||||||
_log.Warn($"Waiting for process {pid} to exit.");
|
|
||||||
waitProc.WaitForExit();
|
|
||||||
_log.Info("Continuing in 5 seconds.");
|
_log.Info("Continuing in 5 seconds.");
|
||||||
Thread.Sleep(5000);
|
Thread.Sleep(5000);
|
||||||
|
if (!waitProc.HasExited)
|
||||||
|
{
|
||||||
|
_log.Warn($"Killing old process {pid}.");
|
||||||
|
waitProc.Kill();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
[assembly: AssemblyVersion("1.1.207.7")]
|
[assembly: AssemblyVersion("1.1.229.265")]
|
||||||
[assembly: AssemblyFileVersion("1.1.207.7")]
|
[assembly: AssemblyFileVersion("1.1.229.265")]
|
@@ -185,6 +185,7 @@
|
|||||||
<Reference Include="PresentationFramework" />
|
<Reference Include="PresentationFramework" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="ListBoxExtensions.cs" />
|
||||||
<Compile Include="Managers\InstanceManager.cs" />
|
<Compile Include="Managers\InstanceManager.cs" />
|
||||||
<Compile Include="NativeMethods.cs" />
|
<Compile Include="NativeMethods.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs">
|
<Compile Include="Properties\AssemblyInfo.cs">
|
||||||
|
@@ -77,10 +77,9 @@ namespace Torch.Server
|
|||||||
MySessionComponentExtDebug.ForceDisable = true;
|
MySessionComponentExtDebug.ForceDisable = true;
|
||||||
MyPerServerSettings.AppId = 244850;
|
MyPerServerSettings.AppId = 244850;
|
||||||
MyFinalBuildConstants.APP_VERSION = MyPerGameSettings.BasicGameInfo.GameVersion;
|
MyFinalBuildConstants.APP_VERSION = MyPerGameSettings.BasicGameInfo.GameVersion;
|
||||||
|
|
||||||
MyObjectBuilderSerializer.RegisterFromAssembly(typeof(MyObjectBuilder_CheckpointSerializer).Assembly);
|
|
||||||
InvokeBeforeRun();
|
InvokeBeforeRun();
|
||||||
|
|
||||||
|
//MyObjectBuilderSerializer.RegisterFromAssembly(typeof(MyObjectBuilder_CheckpointSerializer).Assembly);
|
||||||
MyPlugins.RegisterGameAssemblyFile(MyPerGameSettings.GameModAssembly);
|
MyPlugins.RegisterGameAssemblyFile(MyPerGameSettings.GameModAssembly);
|
||||||
MyPlugins.RegisterGameObjectBuildersAssemblyFile(MyPerGameSettings.GameModObjBuildersAssembly);
|
MyPlugins.RegisterGameObjectBuildersAssemblyFile(MyPerGameSettings.GameModObjBuildersAssembly);
|
||||||
MyPlugins.RegisterSandboxAssemblyFile(MyPerGameSettings.SandboxAssembly);
|
MyPlugins.RegisterSandboxAssemblyFile(MyPerGameSettings.SandboxAssembly);
|
||||||
@@ -88,6 +87,7 @@ namespace Torch.Server
|
|||||||
MyPlugins.Load();
|
MyPlugins.Load();
|
||||||
MyGlobalTypeMetadata.Static.Init();
|
MyGlobalTypeMetadata.Static.Init();
|
||||||
|
|
||||||
|
GetManager<InstanceManager>().LoadInstance(Config.InstancePath);
|
||||||
Plugins.LoadPlugins();
|
Plugins.LoadPlugins();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,7 +131,6 @@ namespace Torch.Server
|
|||||||
_uptime = Stopwatch.StartNew();
|
_uptime = Stopwatch.StartNew();
|
||||||
IsRunning = true;
|
IsRunning = true;
|
||||||
GameThread = Thread.CurrentThread;
|
GameThread = Thread.CurrentThread;
|
||||||
Config.Save();
|
|
||||||
State = ServerState.Starting;
|
State = ServerState.Starting;
|
||||||
Log.Info("Starting server.");
|
Log.Info("Starting server.");
|
||||||
|
|
||||||
@@ -143,6 +142,8 @@ namespace Torch.Server
|
|||||||
VRage.Service.ExitListenerSTA.OnExit += delegate { MySandboxGame.Static?.Exit(); };
|
VRage.Service.ExitListenerSTA.OnExit += delegate { MySandboxGame.Static?.Exit(); };
|
||||||
|
|
||||||
base.Start();
|
base.Start();
|
||||||
|
//Stops RunInternal from calling MyFileSystem.InitUserSpecific(null), we call it in InstanceManager.
|
||||||
|
MySandboxGame.IsReloading = true;
|
||||||
runInternal.Invoke(null, null);
|
runInternal.Invoke(null, null);
|
||||||
|
|
||||||
MySandboxGame.Log.Close();
|
MySandboxGame.Log.Close();
|
||||||
|
@@ -74,6 +74,12 @@ namespace Torch.Server.ViewModels
|
|||||||
{
|
{
|
||||||
get => _settings.HackSpeedMultiplier; set { _settings.HackSpeedMultiplier = value; OnPropertyChanged(); }
|
get => _settings.HackSpeedMultiplier; set { _settings.HackSpeedMultiplier = value; OnPropertyChanged(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="MyObjectBuilder_SessionSettings.WelderSpeedMultiplier"/>
|
||||||
|
public float WelderSpeedMultiplier
|
||||||
|
{
|
||||||
|
get => _settings.WelderSpeedMultiplier; set { _settings.WelderSpeedMultiplier = value; OnPropertyChanged(); }
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region NPCs
|
#region NPCs
|
||||||
|
@@ -49,12 +49,15 @@ namespace Torch.Server
|
|||||||
|
|
||||||
private void ChatHistory_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
private void ChatHistory_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||||
{
|
{
|
||||||
|
ChatItems.ScrollToItem(ChatItems.Items.Count - 1);
|
||||||
|
/*
|
||||||
if (VisualTreeHelper.GetChildrenCount(ChatItems) > 0)
|
if (VisualTreeHelper.GetChildrenCount(ChatItems) > 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
Border border = (Border)VisualTreeHelper.GetChild(ChatItems, 0);
|
Border border = (Border)VisualTreeHelper.GetChild(ChatItems, 0);
|
||||||
ScrollViewer scrollViewer = (ScrollViewer)VisualTreeHelper.GetChild(border, 0);
|
ScrollViewer scrollViewer = (ScrollViewer)VisualTreeHelper.GetChild(border, 0);
|
||||||
scrollViewer.ScrollToBottom();
|
scrollViewer.ScrollToBottom();
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SendButton_Click(object sender, RoutedEventArgs e)
|
private void SendButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
@@ -104,6 +104,10 @@
|
|||||||
<TextBox Text="{Binding AssemblerSpeedMultiplier}" Margin="3" Width="70" />
|
<TextBox Text="{Binding AssemblerSpeedMultiplier}" Margin="3" Width="70" />
|
||||||
<Label Content="Assembler Speed" />
|
<Label Content="Assembler Speed" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<TextBox Text="{Binding WelderSpeedMultiplier}" Margin="3" Width="70" />
|
||||||
|
<Label Content="Welder Speed" />
|
||||||
|
</StackPanel>
|
||||||
<StackPanel Orientation="Horizontal">
|
<StackPanel Orientation="Horizontal">
|
||||||
<TextBox Text="{Binding GrinderSpeedMultiplier}" Margin="3" Width="70" />
|
<TextBox Text="{Binding GrinderSpeedMultiplier}" Margin="3" Width="70" />
|
||||||
<Label Content="Grinder Speed" />
|
<Label Content="Grinder Speed" />
|
||||||
|
@@ -1,34 +1,7 @@
|
|||||||
using System;
|
using System.Windows;
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows;
|
|
||||||
using System.Windows.Controls;
|
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 System.Xml.Serialization;
|
|
||||||
using NLog;
|
|
||||||
using Sandbox;
|
|
||||||
using Sandbox.Engine.Networking;
|
|
||||||
using Sandbox.Engine.Utils;
|
|
||||||
using Torch.Server.Managers;
|
using Torch.Server.Managers;
|
||||||
using Torch.Server.ViewModels;
|
using Torch.Server.ViewModels;
|
||||||
using Torch.Views;
|
|
||||||
using VRage;
|
|
||||||
using VRage.Dedicated;
|
|
||||||
using VRage.Game;
|
|
||||||
using VRage.ObjectBuilders;
|
|
||||||
using Path = System.IO.Path;
|
|
||||||
|
|
||||||
namespace Torch.Server.Views
|
namespace Torch.Server.Views
|
||||||
{
|
{
|
||||||
|
@@ -39,7 +39,7 @@
|
|||||||
</StackPanel>
|
</StackPanel>
|
||||||
<TabControl Grid.Row="1" Height="Auto" x:Name="TabControl" Margin="5,0,5,5">
|
<TabControl Grid.Row="1" Height="Auto" x:Name="TabControl" Margin="5,0,5,5">
|
||||||
<TabItem Header="Configuration">
|
<TabItem Header="Configuration">
|
||||||
<Grid>
|
<Grid IsEnabled="{Binding IsRunning, Converter={StaticResource InverseBool}}">
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
<RowDefinition/>
|
<RowDefinition/>
|
||||||
|
@@ -65,7 +65,7 @@ namespace Torch.Server
|
|||||||
|
|
||||||
private void BtnStart_Click(object sender, RoutedEventArgs e)
|
private void BtnStart_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
_config.Save();
|
_server.GetManager<InstanceManager>().SaveConfig();
|
||||||
new Thread(_server.Start).Start();
|
new Thread(_server.Start).Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,7 +80,6 @@ namespace Torch.Server
|
|||||||
_config.WindowSize = newSize;
|
_config.WindowSize = newSize;
|
||||||
var newPos = new Point((int)Left, (int)Top);
|
var newPos = new Point((int)Left, (int)Top);
|
||||||
_config.WindowPosition = newPos;
|
_config.WindowPosition = newPos;
|
||||||
_config.Save();
|
|
||||||
|
|
||||||
if (_server?.State == ServerState.Running)
|
if (_server?.State == ServerState.Running)
|
||||||
_server.Stop();
|
_server.Stop();
|
||||||
|
@@ -40,7 +40,7 @@ namespace Torch.Commands
|
|||||||
|
|
||||||
public bool IsCommand(string command)
|
public bool IsCommand(string command)
|
||||||
{
|
{
|
||||||
return command.Length > 1 && command[0] == Prefix;
|
return !string.IsNullOrEmpty(command) && command[0] == Prefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RegisterCommandModule(Type moduleType, ITorchPlugin plugin = null)
|
public void RegisterCommandModule(Type moduleType, ITorchPlugin plugin = null)
|
||||||
|
@@ -1,8 +1,11 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System.Timers;
|
||||||
using Sandbox.ModAPI;
|
using Sandbox.ModAPI;
|
||||||
using Torch;
|
using Torch;
|
||||||
using Torch.Commands.Permissions;
|
using Torch.Commands.Permissions;
|
||||||
@@ -106,12 +109,48 @@ namespace Torch.Commands
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Command("restart", "Restarts the server.")]
|
[Command("restart", "Restarts the server.")]
|
||||||
public void Restart(bool save = true)
|
public void Restart(int countdownSeconds = 10, bool save = true)
|
||||||
{
|
{
|
||||||
Context.Respond("Restarting server.");
|
Task.Run(() =>
|
||||||
if (save)
|
{
|
||||||
Context.Torch.Save(Context.Player?.IdentityId ?? 0).Wait();
|
var countdown = RestartCountdown(countdownSeconds).GetEnumerator();
|
||||||
|
while (countdown.MoveNext())
|
||||||
|
{
|
||||||
|
Thread.Sleep(1000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable RestartCountdown(int countdown)
|
||||||
|
{
|
||||||
|
for (var i = countdown; i >= 0; i--)
|
||||||
|
{
|
||||||
|
if (i >= 60 && i % 60 == 0)
|
||||||
|
{
|
||||||
|
Context.Torch.Multiplayer.SendMessage($"Restarting server in {i / 60} minute{Pluralize(i / 60)}.");
|
||||||
|
yield return null;
|
||||||
|
}
|
||||||
|
else if (i > 0)
|
||||||
|
{
|
||||||
|
if (i < 11)
|
||||||
|
Context.Torch.Multiplayer.SendMessage($"Restarting server in {i} second{Pluralize(i)}.");
|
||||||
|
yield return null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Context.Torch.Invoke(() =>
|
||||||
|
{
|
||||||
|
Context.Torch.Save(0).Wait();
|
||||||
Context.Torch.Restart();
|
Context.Torch.Restart();
|
||||||
|
});
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string Pluralize(int num)
|
||||||
|
{
|
||||||
|
return num == 1 ? "" : "s";
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@@ -45,7 +45,7 @@ namespace Torch.Managers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Static_ChatMessageReceived(ulong arg1, string arg2, SteamSDK.ChatEntryTypeEnum arg3)
|
private void Static_ChatMessageReceived(ulong arg1, string arg2)
|
||||||
{
|
{
|
||||||
var msg = new ChatMsg {Author = arg1, Text = arg2};
|
var msg = new ChatMsg {Author = arg1, Text = arg2};
|
||||||
var sendToOthers = true;
|
var sendToOthers = true;
|
||||||
|
@@ -28,6 +28,7 @@ using Torch.Commands;
|
|||||||
using Torch.ViewModels;
|
using Torch.ViewModels;
|
||||||
using VRage.Game;
|
using VRage.Game;
|
||||||
using VRage.Game.ModAPI;
|
using VRage.Game.ModAPI;
|
||||||
|
using VRage.GameServices;
|
||||||
using VRage.Library.Collections;
|
using VRage.Library.Collections;
|
||||||
using VRage.Network;
|
using VRage.Network;
|
||||||
using VRage.Utils;
|
using VRage.Utils;
|
||||||
@@ -120,6 +121,9 @@ namespace Torch.Managers
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void SendMessage(string message, string author = "Server", long playerId = 0, string font = MyFontEnum.Red)
|
public void SendMessage(string message, string author = "Server", long playerId = 0, string font = MyFontEnum.Red)
|
||||||
{
|
{
|
||||||
|
if (string.IsNullOrEmpty(message))
|
||||||
|
return;
|
||||||
|
|
||||||
ChatHistory.Add(new ChatMessage(DateTime.Now, 0, author, message));
|
ChatHistory.Add(new ChatMessage(DateTime.Now, 0, author, message));
|
||||||
var commands = Torch.GetManager<CommandManager>();
|
var commands = Torch.GetManager<CommandManager>();
|
||||||
if (commands.IsCommand(message))
|
if (commands.IsCommand(message))
|
||||||
@@ -166,10 +170,10 @@ namespace Torch.Managers
|
|||||||
|
|
||||||
private void OnClientKicked(ulong steamId)
|
private void OnClientKicked(ulong steamId)
|
||||||
{
|
{
|
||||||
OnClientLeft(steamId, ChatMemberStateChangeEnum.Kicked);
|
OnClientLeft(steamId, MyChatMemberStateChangeEnum.Kicked);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnClientLeft(ulong steamId, ChatMemberStateChangeEnum stateChange)
|
private void OnClientLeft(ulong steamId, MyChatMemberStateChangeEnum stateChange)
|
||||||
{
|
{
|
||||||
Players.TryGetValue(steamId, out PlayerViewModel vm);
|
Players.TryGetValue(steamId, out PlayerViewModel vm);
|
||||||
if (vm == null)
|
if (vm == null)
|
||||||
|
@@ -126,8 +126,7 @@ namespace Torch.Managers
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_log.Fatal(ex);
|
_log.Error(ex);
|
||||||
_log.Fatal(ex, "~Error processing event!");
|
|
||||||
//crash after logging, bad things could happen if we continue on with bad data
|
//crash after logging, bad things could happen if we continue on with bad data
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
@@ -200,8 +199,8 @@ namespace Torch.Managers
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_log.Fatal(ex);
|
_log.Error(ex, "Error processing network event!");
|
||||||
_log.Fatal(ex, "Error when returning control to game server!");
|
_log.Error(ex);
|
||||||
//crash after logging, bad things could happen if we continue on with bad data
|
//crash after logging, bad things could happen if we continue on with bad data
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
@@ -121,9 +121,10 @@ namespace Torch.Managers
|
|||||||
|
|
||||||
commands.RegisterPluginCommands(plugin);
|
commands.RegisterPluginCommands(plugin);
|
||||||
}
|
}
|
||||||
catch
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
_log.Error($"Error loading plugin '{type.FullName}'");
|
_log.Error($"Error loading plugin '{type.FullName}'");
|
||||||
|
_log.Error(e);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -6,6 +6,7 @@ using System.IO.Packaging;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using NLog;
|
using NLog;
|
||||||
@@ -52,7 +53,8 @@ namespace Torch.Managers
|
|||||||
return new Tuple<Version, string>(new Version(), null);
|
return new Tuple<Version, string>(new Version(), null);
|
||||||
|
|
||||||
var zip = latest.Assets.FirstOrDefault(x => x.Name.Contains(".zip"));
|
var zip = latest.Assets.FirstOrDefault(x => x.Name.Contains(".zip"));
|
||||||
return new Tuple<Version, string>(new Version(latest.TagName ?? "0"), zip?.BrowserDownloadUrl);
|
var versionName = Regex.Match(latest.TagName, "(\\d+\\.)+\\d+").ToString();
|
||||||
|
return new Tuple<Version, string>(new Version(string.IsNullOrWhiteSpace(versionName) ? versionName : "0.0"), zip?.BrowserDownloadUrl);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -67,6 +69,8 @@ namespace Torch.Managers
|
|||||||
if (!Torch.Config.GetPluginUpdates)
|
if (!Torch.Config.GetPluginUpdates)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
var name = manifest.Repository.Split('/');
|
var name = manifest.Repository.Split('/');
|
||||||
if (name.Length != 2)
|
if (name.Length != 2)
|
||||||
{
|
{
|
||||||
@@ -90,12 +94,20 @@ namespace Torch.Managers
|
|||||||
_log.Info($"{manifest.Repository} is up to date. ({currentVersion})");
|
_log.Info($"{manifest.Repository} is up to date. ({currentVersion})");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_log.Error($"An error occured downloading the plugin update for {manifest.Repository}.");
|
||||||
|
_log.Error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async void CheckAndUpdateTorch()
|
private async void CheckAndUpdateTorch()
|
||||||
{
|
{
|
||||||
if (!Torch.Config.GetTorchUpdates)
|
if (!Torch.Config.GetTorchUpdates)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
var releaseInfo = await GetLatestRelease("TorchAPI", "Torch").ConfigureAwait(false);
|
var releaseInfo = await GetLatestRelease("TorchAPI", "Torch").ConfigureAwait(false);
|
||||||
if (releaseInfo.Item1 > Torch.TorchVersion)
|
if (releaseInfo.Item1 > Torch.TorchVersion)
|
||||||
{
|
{
|
||||||
@@ -104,12 +116,19 @@ namespace Torch.Managers
|
|||||||
new WebClient().DownloadFile(new Uri(releaseInfo.Item2), updateName);
|
new WebClient().DownloadFile(new Uri(releaseInfo.Item2), updateName);
|
||||||
UpdateFromZip(updateName, _torchDir);
|
UpdateFromZip(updateName, _torchDir);
|
||||||
File.Delete(updateName);
|
File.Delete(updateName);
|
||||||
|
_log.Warn($"Torch version {releaseInfo.Item1} has been installed, please restart Torch to finish the process.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_log.Info("Torch is up to date.");
|
_log.Info("Torch is up to date.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_log.Error("An error occured downloading the Torch update.");
|
||||||
|
_log.Error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void UpdateFromZip(string zipFile, string extractPath)
|
private void UpdateFromZip(string zipFile, string extractPath)
|
||||||
{
|
{
|
||||||
|
@@ -4,6 +4,7 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using SteamSDK;
|
using SteamSDK;
|
||||||
|
using VRage.Steam;
|
||||||
using Sandbox;
|
using Sandbox;
|
||||||
|
|
||||||
namespace Torch
|
namespace Torch
|
||||||
@@ -16,34 +17,48 @@ namespace Torch
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class SteamService : MySteamService
|
public class SteamService : MySteamService
|
||||||
{
|
{
|
||||||
public SteamService(bool isDedicated, uint appId) : base(true, appId)
|
public SteamService(bool isDedicated, uint appId)
|
||||||
|
: base(true, appId)
|
||||||
{
|
{
|
||||||
// TODO: Add protection for this mess... somewhere
|
// TODO: Add protection for this mess... somewhere
|
||||||
SteamServerAPI.Instance.Dispose();
|
SteamSDK.SteamServerAPI.Instance.Dispose();
|
||||||
var steam = typeof(MySteamService);
|
var steam = typeof(MySteamService);
|
||||||
steam.GetField("SteamServerAPI").SetValue(this, null);
|
|
||||||
|
steam.GetProperty("SteamServerAPI").GetSetMethod(true).Invoke(this, new object[] { null });
|
||||||
|
steam.GetField("m_gameServer", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).SetValue(this, null);
|
||||||
|
|
||||||
steam.GetProperty("AppId").GetSetMethod(true).Invoke(this, new object[] { appId });
|
steam.GetProperty("AppId").GetSetMethod(true).Invoke(this, new object[] { appId });
|
||||||
if (isDedicated)
|
if (isDedicated)
|
||||||
{
|
{
|
||||||
steam.GetField("SteamServerAPI").SetValue(this, SteamServerAPI.Instance);
|
steam.GetProperty("SteamServerAPI").GetSetMethod(true).Invoke(this, new object[] { null });
|
||||||
|
steam.GetField("m_gameServer").SetValue(this, new MySteamGameServer());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var steamApi = SteamAPI.Instance;
|
var SteamAPI = SteamSDK.SteamAPI.Instance;
|
||||||
steam.GetField("SteamAPI").SetValue(this, SteamAPI.Instance);
|
steam.GetProperty("API").GetSetMethod(true).Invoke(this, new object[] { SteamAPI.Instance });
|
||||||
steam.GetProperty("IsActive").GetSetMethod(true).Invoke(this, new object[] { SteamAPI.Instance != null });
|
steam.GetProperty("IsActive").GetSetMethod(true).Invoke(this, new object[] {
|
||||||
|
SteamAPI.Instance.Init()
|
||||||
|
});
|
||||||
|
|
||||||
if (steamApi != null)
|
if (IsActive)
|
||||||
{
|
{
|
||||||
steam.GetProperty("UserId").GetSetMethod(true).Invoke(this, new object[] { steamApi.GetSteamUserId() });
|
steam.GetProperty("UserId").GetSetMethod(true).Invoke(this, new object[] { SteamAPI.GetSteamUserId() });
|
||||||
steam.GetProperty("UserName").GetSetMethod(true).Invoke(this, new object[] { steamApi.GetSteamName() });
|
steam.GetProperty("UserName").GetSetMethod(true).Invoke(this, new object[] { SteamAPI.GetSteamName() });
|
||||||
steam.GetProperty("OwnsGame").GetSetMethod(true).Invoke(this, new object[] { steamApi.HasGame() });
|
steam.GetProperty("OwnsGame").GetSetMethod(true).Invoke(this, new object[] { SteamAPI.HasGame() });
|
||||||
steam.GetProperty("UserUniverse").GetSetMethod(true).Invoke(this, new object[] { steamApi.GetSteamUserUniverse() });
|
steam.GetProperty("UserUniverse").GetSetMethod(true).Invoke(this, new object[] { SteamAPI.GetSteamUserUniverse() });
|
||||||
steam.GetProperty("BranchName").GetSetMethod(true).Invoke(this, new object[] { steamApi.GetBranchName() });
|
steam.GetProperty("BranchName").GetSetMethod(true).Invoke(this, new object[] { SteamAPI.GetBranchName() });
|
||||||
steamApi.LoadStats();
|
SteamAPI.LoadStats();
|
||||||
}
|
|
||||||
}
|
steam.GetProperty("InventoryAPI").GetSetMethod(true).Invoke(this, new object[] { new MySteamInventory() });
|
||||||
|
|
||||||
|
steam.GetMethod("RegisterCallbacks",
|
||||||
|
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)
|
||||||
|
.Invoke(this, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
steam.GetProperty("Peer2Peer").GetSetMethod(true).Invoke(this, new object[] { new MySteamPeer2Peer() });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -142,6 +142,9 @@
|
|||||||
<HintPath>..\GameBinaries\VRage.Scripting.dll</HintPath>
|
<HintPath>..\GameBinaries\VRage.Scripting.dll</HintPath>
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="VRage.Steam">
|
||||||
|
<HintPath>..\..\..\..\..\..\..\steamcmd\steamapps\common\SpaceEngineersDedicatedServer\DedicatedServer64\VRage.Steam.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="WindowsBase" />
|
<Reference Include="WindowsBase" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
Reference in New Issue
Block a user