diff --git a/CHANGELOG.md b/CHANGELOG.md
index 26db267..73b7085 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,12 @@
+# 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
- This release makes significant changes to TorchConfig.xml. It has been renamed to Torch.cfg and has different options.
diff --git a/Torch.Client/Properties/AssemblyInfo.cs b/Torch.Client/Properties/AssemblyInfo.cs
index fc07d79..be8ba40 100644
--- a/Torch.Client/Properties/AssemblyInfo.cs
+++ b/Torch.Client/Properties/AssemblyInfo.cs
@@ -1,4 +1,4 @@
using System.Reflection;
-[assembly: AssemblyVersion("1.0.213.390")]
-[assembly: AssemblyFileVersion("1.0.213.390")]
\ No newline at end of file
+[assembly: AssemblyVersion("1.0.229.265")]
+[assembly: AssemblyFileVersion("1.0.229.265")]
\ No newline at end of file
diff --git a/Torch.Client/Torch.Client.csproj b/Torch.Client/Torch.Client.csproj
index f279cf8..66d3145 100644
--- a/Torch.Client/Torch.Client.csproj
+++ b/Torch.Client/Torch.Client.csproj
@@ -103,6 +103,9 @@
..\GameBinaries\VRage.Render11.dll
False
+
+ ..\..\..\..\..\..\..\steamcmd\steamapps\common\SpaceEngineersDedicatedServer\DedicatedServer64\VRage.Steam.dll
+
diff --git a/Torch.Client/TorchClient.cs b/Torch.Client/TorchClient.cs
index 350cb60..719fdf4 100644
--- a/Torch.Client/TorchClient.cs
+++ b/Torch.Client/TorchClient.cs
@@ -11,6 +11,7 @@ using Sandbox.Engine.Utils;
using Sandbox.Game;
using Sandbox.ModAPI;
using SpaceEngineers.Game;
+using VRage.Steam;
using Torch.API;
using VRage.FileSystem;
using VRageRender;
@@ -22,7 +23,6 @@ namespace Torch.Client
private MyCommonProgramStartup _startup;
private IMyRender _renderer;
private const uint APP_ID = 244850;
- private VRageGameServices _services;
public override void Init()
{
@@ -59,7 +59,6 @@ namespace Torch.Client
InitializeRender();
- _services = new VRageGameServices(mySteamService);
if (!Game.IsDedicated)
MyFileSystem.InitUserSpecific(mySteamService.UserId.ToString());
}
@@ -85,7 +84,7 @@ namespace Torch.Client
public override void Start()
{
- using (var spaceEngineersGame = new SpaceEngineersGame(_services, RunArgs))
+ using (var spaceEngineersGame = new SpaceEngineersGame(RunArgs))
{
Log.Info("Starting client");
spaceEngineersGame.OnGameLoaded += SpaceEngineersGame_OnGameLoaded;
diff --git a/Torch.Server/ListBoxExtensions.cs b/Torch.Server/ListBoxExtensions.cs
new file mode 100644
index 0000000..adcc22f
--- /dev/null
+++ b/Torch.Server/ListBoxExtensions.cs
@@ -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);
+ }
+ }
+}
diff --git a/Torch.Server/Managers/InstanceManager.cs b/Torch.Server/Managers/InstanceManager.cs
index b9b1d91..11a689e 100644
--- a/Torch.Server/Managers/InstanceManager.cs
+++ b/Torch.Server/Managers/InstanceManager.cs
@@ -129,7 +129,7 @@ namespace Torch.Server.Managers
public void SaveConfig()
{
- DedicatedConfig.Model.Save();
+ DedicatedConfig.Save();
Log.Info("Saved dedicated config.");
try
diff --git a/Torch.Server/Properties/AssemblyInfo.cs b/Torch.Server/Properties/AssemblyInfo.cs
index 1ef7f82..34b834d 100644
--- a/Torch.Server/Properties/AssemblyInfo.cs
+++ b/Torch.Server/Properties/AssemblyInfo.cs
@@ -1,4 +1,4 @@
using System.Reflection;
-[assembly: AssemblyVersion("1.1.213.390")]
-[assembly: AssemblyFileVersion("1.1.213.390")]
\ No newline at end of file
+[assembly: AssemblyVersion("1.1.229.265")]
+[assembly: AssemblyFileVersion("1.1.229.265")]
\ No newline at end of file
diff --git a/Torch.Server/Torch.Server.csproj b/Torch.Server/Torch.Server.csproj
index 34742d8..e57334d 100644
--- a/Torch.Server/Torch.Server.csproj
+++ b/Torch.Server/Torch.Server.csproj
@@ -185,6 +185,7 @@
+
diff --git a/Torch.Server/TorchServer.cs b/Torch.Server/TorchServer.cs
index 7df0d0a..41df9e5 100644
--- a/Torch.Server/TorchServer.cs
+++ b/Torch.Server/TorchServer.cs
@@ -79,7 +79,7 @@ namespace Torch.Server
MyFinalBuildConstants.APP_VERSION = MyPerGameSettings.BasicGameInfo.GameVersion;
InvokeBeforeRun();
- MyObjectBuilderSerializer.RegisterFromAssembly(typeof(MyObjectBuilder_CheckpointSerializer).Assembly);
+ //MyObjectBuilderSerializer.RegisterFromAssembly(typeof(MyObjectBuilder_CheckpointSerializer).Assembly);
MyPlugins.RegisterGameAssemblyFile(MyPerGameSettings.GameModAssembly);
MyPlugins.RegisterGameObjectBuildersAssemblyFile(MyPerGameSettings.GameModObjBuildersAssembly);
MyPlugins.RegisterSandboxAssemblyFile(MyPerGameSettings.SandboxAssembly);
@@ -131,7 +131,6 @@ namespace Torch.Server
_uptime = Stopwatch.StartNew();
IsRunning = true;
GameThread = Thread.CurrentThread;
- Config.Save();
State = ServerState.Starting;
Log.Info("Starting server.");
diff --git a/Torch.Server/ViewModels/SessionSettingsViewModel.cs b/Torch.Server/ViewModels/SessionSettingsViewModel.cs
index 4dc3875..f354dd5 100644
--- a/Torch.Server/ViewModels/SessionSettingsViewModel.cs
+++ b/Torch.Server/ViewModels/SessionSettingsViewModel.cs
@@ -74,6 +74,12 @@ namespace Torch.Server.ViewModels
{
get => _settings.HackSpeedMultiplier; set { _settings.HackSpeedMultiplier = value; OnPropertyChanged(); }
}
+
+ ///
+ public float WelderSpeedMultiplier
+ {
+ get => _settings.WelderSpeedMultiplier; set { _settings.WelderSpeedMultiplier = value; OnPropertyChanged(); }
+ }
#endregion
#region NPCs
diff --git a/Torch.Server/Views/ChatControl.xaml.cs b/Torch.Server/Views/ChatControl.xaml.cs
index 832f329..03bab57 100644
--- a/Torch.Server/Views/ChatControl.xaml.cs
+++ b/Torch.Server/Views/ChatControl.xaml.cs
@@ -49,12 +49,15 @@ namespace Torch.Server
private void ChatHistory_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
+ ChatItems.ScrollToItem(ChatItems.Items.Count - 1);
+ /*
if (VisualTreeHelper.GetChildrenCount(ChatItems) > 0)
{
+
Border border = (Border)VisualTreeHelper.GetChild(ChatItems, 0);
ScrollViewer scrollViewer = (ScrollViewer)VisualTreeHelper.GetChild(border, 0);
scrollViewer.ScrollToBottom();
- }
+ }*/
}
private void SendButton_Click(object sender, RoutedEventArgs e)
diff --git a/Torch.Server/Views/ConfigControl.xaml b/Torch.Server/Views/ConfigControl.xaml
index 864fc94..d8b8327 100644
--- a/Torch.Server/Views/ConfigControl.xaml
+++ b/Torch.Server/Views/ConfigControl.xaml
@@ -104,6 +104,10 @@
+
+
+
+
diff --git a/Torch.Server/Views/ConfigControl.xaml.cs b/Torch.Server/Views/ConfigControl.xaml.cs
index 298a243..bc0f94d 100644
--- a/Torch.Server/Views/ConfigControl.xaml.cs
+++ b/Torch.Server/Views/ConfigControl.xaml.cs
@@ -1,34 +1,7 @@
-using System;
-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;
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.ViewModels;
-using Torch.Views;
-using VRage;
-using VRage.Dedicated;
-using VRage.Game;
-using VRage.ObjectBuilders;
-using Path = System.IO.Path;
namespace Torch.Server.Views
{
diff --git a/Torch.Server/Views/TorchUI.xaml.cs b/Torch.Server/Views/TorchUI.xaml.cs
index 33f530e..92b1083 100644
--- a/Torch.Server/Views/TorchUI.xaml.cs
+++ b/Torch.Server/Views/TorchUI.xaml.cs
@@ -65,7 +65,7 @@ namespace Torch.Server
private void BtnStart_Click(object sender, RoutedEventArgs e)
{
- _config.Save();
+ _server.GetManager().SaveConfig();
new Thread(_server.Start).Start();
}
@@ -80,7 +80,6 @@ namespace Torch.Server
_config.WindowSize = newSize;
var newPos = new Point((int)Left, (int)Top);
_config.WindowPosition = newPos;
- _config.Save();
if (_server?.State == ServerState.Running)
_server.Stop();
diff --git a/Torch/Commands/TorchCommands.cs b/Torch/Commands/TorchCommands.cs
index 3b01d14..7091385 100644
--- a/Torch/Commands/TorchCommands.cs
+++ b/Torch/Commands/TorchCommands.cs
@@ -1,8 +1,11 @@
using System;
+using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
+using System.Threading;
using System.Threading.Tasks;
+using System.Timers;
using Sandbox.ModAPI;
using Torch;
using Torch.Commands.Permissions;
@@ -106,12 +109,48 @@ namespace Torch.Commands
}
[Command("restart", "Restarts the server.")]
- public void Restart(bool save = true)
+ public void Restart(int countdownSeconds = 10, bool save = true)
{
- Context.Respond("Restarting server.");
- if (save)
- Context.Torch.Save(Context.Player?.IdentityId ?? 0).Wait();
- Context.Torch.Restart();
+ Task.Run(() =>
+ {
+ 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();
+ });
+ yield break;
+ }
+ }
+ }
+
+ private string Pluralize(int num)
+ {
+ return num == 1 ? "" : "s";
}
///
diff --git a/Torch/Managers/ChatManager.cs b/Torch/Managers/ChatManager.cs
index 3468ba0..a2de253 100644
--- a/Torch/Managers/ChatManager.cs
+++ b/Torch/Managers/ChatManager.cs
@@ -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 sendToOthers = true;
diff --git a/Torch/Managers/MultiplayerManager.cs b/Torch/Managers/MultiplayerManager.cs
index 8c7205a..def01c5 100644
--- a/Torch/Managers/MultiplayerManager.cs
+++ b/Torch/Managers/MultiplayerManager.cs
@@ -28,6 +28,7 @@ using Torch.Commands;
using Torch.ViewModels;
using VRage.Game;
using VRage.Game.ModAPI;
+using VRage.GameServices;
using VRage.Library.Collections;
using VRage.Network;
using VRage.Utils;
@@ -169,10 +170,10 @@ namespace Torch.Managers
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);
if (vm == null)
diff --git a/Torch/Managers/UpdateManager.cs b/Torch/Managers/UpdateManager.cs
index 59b0634..d51c9bd 100644
--- a/Torch/Managers/UpdateManager.cs
+++ b/Torch/Managers/UpdateManager.cs
@@ -6,6 +6,7 @@ using System.IO.Packaging;
using System.Linq;
using System.Net;
using System.Text;
+using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using NLog;
@@ -52,7 +53,8 @@ namespace Torch.Managers
return new Tuple(new Version(), null);
var zip = latest.Assets.FirstOrDefault(x => x.Name.Contains(".zip"));
- return new Tuple(new Version(latest.TagName ?? "0"), zip?.BrowserDownloadUrl);
+ var versionName = Regex.Match(latest.TagName, "(\\d+\\.)+\\d+").ToString();
+ return new Tuple(new Version(string.IsNullOrWhiteSpace(versionName) ? versionName : "0.0"), zip?.BrowserDownloadUrl);
}
catch (Exception e)
{
@@ -114,6 +116,7 @@ namespace Torch.Managers
new WebClient().DownloadFile(new Uri(releaseInfo.Item2), updateName);
UpdateFromZip(updateName, _torchDir);
File.Delete(updateName);
+ _log.Warn($"Torch version {releaseInfo.Item1} has been installed, please restart Torch to finish the process.");
}
else
{
diff --git a/Torch/SteamService.cs b/Torch/SteamService.cs
index 7dff154..4044bc5 100644
--- a/Torch/SteamService.cs
+++ b/Torch/SteamService.cs
@@ -4,6 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SteamSDK;
+using VRage.Steam;
using Sandbox;
namespace Torch
@@ -16,34 +17,48 @@ namespace Torch
///
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
- SteamServerAPI.Instance.Dispose();
+ SteamSDK.SteamServerAPI.Instance.Dispose();
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 });
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
{
- var steamApi = SteamAPI.Instance;
- steam.GetField("SteamAPI").SetValue(this, SteamAPI.Instance);
- steam.GetProperty("IsActive").GetSetMethod(true).Invoke(this, new object[] { SteamAPI.Instance != null });
+ var SteamAPI = SteamSDK.SteamAPI.Instance;
+ steam.GetProperty("API").GetSetMethod(true).Invoke(this, new object[] { SteamAPI.Instance });
+ 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("UserName").GetSetMethod(true).Invoke(this, new object[] { steamApi.GetSteamName() });
- steam.GetProperty("OwnsGame").GetSetMethod(true).Invoke(this, new object[] { steamApi.HasGame() });
- steam.GetProperty("UserUniverse").GetSetMethod(true).Invoke(this, new object[] { steamApi.GetSteamUserUniverse() });
- steam.GetProperty("BranchName").GetSetMethod(true).Invoke(this, new object[] { steamApi.GetBranchName() });
- steamApi.LoadStats();
+ steam.GetProperty("UserId").GetSetMethod(true).Invoke(this, new object[] { SteamAPI.GetSteamUserId() });
+ steam.GetProperty("UserName").GetSetMethod(true).Invoke(this, new object[] { SteamAPI.GetSteamName() });
+ steam.GetProperty("OwnsGame").GetSetMethod(true).Invoke(this, new object[] { SteamAPI.HasGame() });
+ steam.GetProperty("UserUniverse").GetSetMethod(true).Invoke(this, new object[] { SteamAPI.GetSteamUserUniverse() });
+ steam.GetProperty("BranchName").GetSetMethod(true).Invoke(this, new object[] { SteamAPI.GetBranchName() });
+ 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() });
}
}
}
diff --git a/Torch/Torch.csproj b/Torch/Torch.csproj
index b36d79d..b2f5cb3 100644
--- a/Torch/Torch.csproj
+++ b/Torch/Torch.csproj
@@ -142,6 +142,9 @@
..\GameBinaries\VRage.Scripting.dll
False
+
+ ..\..\..\..\..\..\..\steamcmd\steamapps\common\SpaceEngineersDedicatedServer\DedicatedServer64\VRage.Steam.dll
+