diff --git a/TestPlugin/Commands.cs b/TestPlugin/Commands.cs deleted file mode 100644 index 6617b26..0000000 --- a/TestPlugin/Commands.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Sandbox; -using Sandbox.Game.Entities; -using Sandbox.Game.World; -using Torch.Commands; -using VRage.Game.Entity; -using VRage.Game.ModAPI; - -namespace TestPlugin -{ - public class Commands : CommandModule - { - [Command("Ban", "Bans a player from the game")] - public void Ban() - { - Context.Torch.Multiplayer.SendMessage("Boop!"); - } - - [Command("Unban", "Unbans a player from the game")] - public void Unban() - { - Context.Torch.Multiplayer.SendMessage("Beep!"); - } - } -} diff --git a/TestPlugin/Plugin.cs b/TestPlugin/Plugin.cs deleted file mode 100644 index 6017a95..0000000 --- a/TestPlugin/Plugin.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Torch; -using Torch.API; -using VRage.Plugins; - -namespace TestPlugin -{ - [Plugin("Test Plugin", "1.3.3.7", "fed85d8d-8a29-4ab0-9869-4ad121f99d04")] - public class Plugin : TorchPluginBase - { - /// - public override void Init(ITorchBase torch) - { - base.Init(torch); - //Torch.Log.Write($"Plugin init {Name}"); - } - - /// - public override void Update() - { - //Torch.Log.Write($"Plugin update {Name}"); - } - - /// - public override void Dispose() - { - //Torch.Log.Write($"Plugin unload {Name}"); - } - } -} diff --git a/TestPlugin/Properties/AssemblyInfo.cs b/TestPlugin/Properties/AssemblyInfo.cs deleted file mode 100644 index 95ea997..0000000 --- a/TestPlugin/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("TestPlugin")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("TestPlugin")] -[assembly: AssemblyCopyright("Copyright © 2016")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("abd18a6c-f638-44e9-8e55-dedea321c600")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/TestPlugin/TestPlugin.csproj b/TestPlugin/TestPlugin.csproj deleted file mode 100644 index 21772c3..0000000 --- a/TestPlugin/TestPlugin.csproj +++ /dev/null @@ -1,70 +0,0 @@ - - - - - Debug - AnyCPU - {ABD18A6C-F638-44E9-8E55-DEDEA321C600} - Library - Properties - TestPlugin - TestPlugin - v4.6.1 - 512 - - - true - bin\x64\Debug\ - DEBUG;TRACE - full - x64 - prompt - MinimumRecommendedRules.ruleset - - - bin\x64\Release\ - TRACE - true - pdbonly - x64 - prompt - MinimumRecommendedRules.ruleset - - - - ..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\Sandbox.Game.dll - - - - - - - - - - - ..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.dll - - - False - ..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.Game.dll - - - - - - - - - - - {FBA5D932-6254-4A1E-BAF4-E229FA94E3C2} - Torch.API - - - {7e01635c-3b67-472e-bcd6-c5539564f214} - Torch - - - - \ No newline at end of file diff --git a/Torch.API/IPlayer.cs b/Torch.API/IPlayer.cs new file mode 100644 index 0000000..db4d09e --- /dev/null +++ b/Torch.API/IPlayer.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VRage.Game.ModAPI; + +namespace Torch.API +{ + public interface IPlayer + { + string Name { get; } + ulong SteamId { get; } + ConnectionState State { get; } + } +} diff --git a/Torch.API/ITorchBase.cs b/Torch.API/ITorchBase.cs index 23a6313..e83aa63 100644 --- a/Torch.API/ITorchBase.cs +++ b/Torch.API/ITorchBase.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using Torch.API.Managers; using VRage.Game.ModAPI; namespace Torch.API @@ -14,7 +15,7 @@ namespace Torch.API event Action SessionUnloading; event Action SessionUnloaded; ITorchConfig Config { get; } - IMultiplayer Multiplayer { get; } + IMultiplayerManager Multiplayer { get; } IPluginManager Plugins { get; } Version TorchVersion { get; } void Invoke(Action action); @@ -25,6 +26,7 @@ namespace Torch.API void Start(); void Stop(); void Init(); + T GetManager() where T : class, IManager; } public interface ITorchServer : ITorchBase diff --git a/Torch.API/Managers/IManager.cs b/Torch.API/Managers/IManager.cs new file mode 100644 index 0000000..6274262 --- /dev/null +++ b/Torch.API/Managers/IManager.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Torch.API.Managers +{ + public interface IManager + { + void Init(); + } +} diff --git a/Torch.API/IMultiplayer.cs b/Torch.API/Managers/IMultiplayerManager.cs similarity index 74% rename from Torch.API/IMultiplayer.cs rename to Torch.API/Managers/IMultiplayerManager.cs index e873657..4a52844 100644 --- a/Torch.API/IMultiplayer.cs +++ b/Torch.API/Managers/IMultiplayerManager.cs @@ -4,20 +4,19 @@ using System.Collections.ObjectModel; using VRage.Game; using VRage.Game.ModAPI; -namespace Torch.API +namespace Torch.API.Managers { public delegate void MessageReceivedDel(IChatMessage message, ref bool sendToOthers); - public interface IMultiplayer + public interface IMultiplayerManager : IManager { - event Action PlayerJoined; - event Action PlayerLeft; + event Action PlayerJoined; + event Action PlayerLeft; event MessageReceivedDel MessageReceived; void SendMessage(string message, string author = "Server", long playerId = 0, string font = MyFontEnum.Blue); void KickPlayer(ulong steamId); void BanPlayer(ulong steamId, bool banned = true); IMyPlayer GetPlayerBySteamId(ulong id); IMyPlayer GetPlayerByName(string name); - List ChatHistory { get; } } } \ No newline at end of file diff --git a/Torch.API/Managers/INetworkManager.cs b/Torch.API/Managers/INetworkManager.cs new file mode 100644 index 0000000..dc14f60 --- /dev/null +++ b/Torch.API/Managers/INetworkManager.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VRage; +using VRage.Library.Collections; +using VRage.Network; + +namespace Torch.API.Managers +{ + public interface INetworkManager : IManager + { + void RegisterNetworkHandler(INetworkHandler handler); + } + + public interface INetworkHandler + { + bool CanHandle(CallSite callSite); + bool Handle(ulong remoteUserId, CallSite site, BitStream stream, object obj, MyPacket packet); + } +} diff --git a/Torch.API/IPluginManager.cs b/Torch.API/Managers/IPluginManager.cs similarity index 74% rename from Torch.API/IPluginManager.cs rename to Torch.API/Managers/IPluginManager.cs index 9453977..7d685ba 100644 --- a/Torch.API/IPluginManager.cs +++ b/Torch.API/Managers/IPluginManager.cs @@ -4,14 +4,13 @@ using Torch.API.Plugins; using VRage.Collections; using VRage.Plugins; -namespace Torch.API +namespace Torch.API.Managers { - public interface IPluginManager : IEnumerable + public interface IPluginManager : IManager, IEnumerable { event Action> PluginsLoaded; List Plugins { get; } void UpdatePlugins(); - void Init(); void DisposePlugins(); } } \ No newline at end of file diff --git a/Torch.API/Torch.API.csproj b/Torch.API/Torch.API.csproj index 6a146de..3a737c3 100644 --- a/Torch.API/Torch.API.csproj +++ b/Torch.API/Torch.API.csproj @@ -35,6 +35,7 @@ False ..\GameBinaries\HavokWrapper.dll + False ..\packages\NLog.4.4.1\lib\net45\NLog.dll @@ -45,30 +46,37 @@ False ..\GameBinaries\Sandbox.Common.dll + False False ..\GameBinaries\Sandbox.Game.dll + False False ..\GameBinaries\Sandbox.Graphics.dll + False False ..\GameBinaries\SpaceEngineers.Game.dll + False False ..\GameBinaries\SpaceEngineers.ObjectBuilders.dll + False False ..\GameBinaries\SpaceEngineers.ObjectBuilders.XmlSerializers.dll + False False ..\GameBinaries\SteamSDK.dll + False @@ -85,59 +93,75 @@ ..\GameBinaries\VRage.dll + False False ..\GameBinaries\VRage.Audio.dll + False ..\GameBinaries\VRage.Dedicated.dll + False False ..\GameBinaries\VRage.Game.dll + False False ..\GameBinaries\VRage.Game.XmlSerializers.dll + False False ..\GameBinaries\VRage.Input.dll + False ..\GameBinaries\VRage.Library.dll + False False ..\GameBinaries\VRage.Math.dll + False False ..\GameBinaries\VRage.Native.dll + False False ..\GameBinaries\VRage.OpenVRWrapper.dll + False False ..\GameBinaries\VRage.Render.dll + False False ..\GameBinaries\VRage.Render11.dll + False False ..\GameBinaries\VRage.Scripting.dll + False - - + + + + + diff --git a/Torch.Client/Properties/AssemblyInfo.cs b/Torch.Client/Properties/AssemblyInfo.cs index cd9dab5..f623ac6 100644 --- a/Torch.Client/Properties/AssemblyInfo.cs +++ b/Torch.Client/Properties/AssemblyInfo.cs @@ -1,4 +1,4 @@ using System.Reflection; -[assembly: AssemblyVersion("1.0.168.389")] -[assembly: AssemblyFileVersion("1.0.168.389")] \ No newline at end of file +[assembly: AssemblyVersion("1.0.169.376")] +[assembly: AssemblyFileVersion("1.0.169.376")] \ No newline at end of file diff --git a/Torch.Client/TorchMainMenuScreen.cs b/Torch.Client/TorchMainMenuScreen.cs index 6ce982f..c0078e4 100644 --- a/Torch.Client/TorchMainMenuScreen.cs +++ b/Torch.Client/TorchMainMenuScreen.cs @@ -1,4 +1,5 @@ -using System; +#pragma warning disable 618 +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -19,6 +20,7 @@ namespace Torch.Client public override void RecreateControls(bool constructor) { base.RecreateControls(constructor); + var buttonSize = MyGuiControlButton.GetVisualStyle(MyGuiControlButtonStyleEnum.Default).NormalTexture.MinSizeGui; Vector2 leftButtonPositionOrigin = MyGuiManager.ComputeFullscreenGuiCoordinate(MyGuiDrawAlignEnum.HORISONTAL_LEFT_AND_VERTICAL_BOTTOM) + new Vector2(buttonSize.X / 2f, 0f); var btn = MakeButton(leftButtonPositionOrigin - 9 * MyGuiConstants.MENU_BUTTONS_POSITION_DELTA, MyStringId.GetOrCompute("Torch"), TorchButtonClicked); diff --git a/Torch.Server/Managers/ConfigManager.cs b/Torch.Server/Managers/ConfigManager.cs new file mode 100644 index 0000000..b655391 --- /dev/null +++ b/Torch.Server/Managers/ConfigManager.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Sandbox.Engine.Utils; +using Torch.API; +using Torch.API.Managers; +using Torch.Managers; +using Torch.Server.ViewModels; +using VRage.Game; + +namespace Torch.Server.Managers +{ + //TODO + public class ConfigManager : Manager + { + private const string CONFIG_NAME = "SpaceEngineers-Dedicated.cfg"; + public ConfigDedicatedViewModel DedicatedConfig { get; set; } + public TorchConfig TorchConfig { get; set; } + + public ConfigManager(ITorchBase torchInstance) : base(torchInstance) + { + + } + + /// + public override void Init() + { + LoadInstance(Torch.Config.InstancePath); + } + + public void LoadInstance(string path) + { + if (!Directory.Exists(path)) + throw new FileNotFoundException($"Instance directory not found at '{path}'"); + + var configPath = Path.Combine(path, CONFIG_NAME); + var config = new MyConfigDedicated(configPath); + config.Load(); + DedicatedConfig = new ConfigDedicatedViewModel(config); + } + + /// + /// Creates a skeleton of a DS instance folder at the given directory. + /// + /// + public void CreateInstance(string path) + { + if (Directory.Exists(path)) + return; + + Directory.CreateDirectory(path); + var savesPath = Path.Combine(path, "Saves"); + Directory.CreateDirectory(savesPath); + var modsPath = Path.Combine(path, "Mods"); + Directory.CreateDirectory(modsPath); + LoadInstance(path); + } + } +} diff --git a/Torch.Server/Managers/DSConfigManager.cs b/Torch.Server/Managers/DSConfigManager.cs deleted file mode 100644 index ef75674..0000000 --- a/Torch.Server/Managers/DSConfigManager.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Sandbox.Engine.Utils; -using Torch.Server.ViewModels; -using VRage.Game; - -namespace Torch.Server.Managers -{ - public class DSConfigManager - { - public ConfigDedicatedViewModel Config { get; set; } - private ConfigDedicatedViewModel _viewModel; - - public DSConfigManager() - { - //Config. - } - - /// - /// Creates a skeleton of a DS instance folder at the given directory. - /// - /// - public void CreateInstance(string path) - { - if (Directory.Exists(path)) - return; - - Directory.CreateDirectory(path); - var saves = Path.Combine(path, "Saves"); - Directory.CreateDirectory(saves); - var mods = Path.Combine(path, "Mods"); - Directory.CreateDirectory(mods); - } - } -} diff --git a/Torch.Server/Program.cs b/Torch.Server/Program.cs index 90710ee..0d357cd 100644 --- a/Torch.Server/Program.cs +++ b/Torch.Server/Program.cs @@ -42,6 +42,9 @@ namespace Torch.Server [STAThread] public static void Main(string[] args) { + //Ensures that all the files are downloaded in the Torch directory. + Directory.SetCurrentDirectory(new FileInfo(typeof(Program).Assembly.Location).Directory.ToString()); + IsManualInstall = Directory.GetCurrentDirectory().Contains("DedicatedServer64"); if (!IsManualInstall) AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; @@ -72,7 +75,7 @@ namespace Torch.Server if (!IsManualInstall) { - new DSConfigManager().CreateInstance("Instance"); + new ConfigManager().CreateInstance("Instance"); options.InstancePath = Path.GetFullPath("Instance"); _log.Warn("Would you like to enable automatic updates? (Y/n):"); @@ -81,7 +84,10 @@ namespace Torch.Server var autoUpdate = !input.Equals("n", StringComparison.InvariantCultureIgnoreCase); options.AutomaticUpdates = autoUpdate; if (autoUpdate) - _log.Info("Automatic updates enabled."); + { + _log.Info("Automatic updates enabled, updating server."); + RunSteamCmd(); + } } //var setupDialog = new FirstTimeSetup { DataContext = options }; @@ -267,11 +273,10 @@ quit"; { try { - var basePath = Path.GetDirectoryName(typeof(Program).Assembly.Location) ?? AppDomain.CurrentDomain.BaseDirectory; - string asmPath = Path.Combine(basePath, "DedicatedServer64", new AssemblyName(args.Name).Name + ".dll"); + var basePath = Path.Combine(Path.GetDirectoryName(typeof(Program).Assembly.Location), "DedicatedServer64"); + string asmPath = Path.Combine(basePath, new AssemblyName(args.Name).Name + ".dll"); if (File.Exists(asmPath)) return Assembly.LoadFrom(asmPath); - } catch { diff --git a/Torch.Server/Properties/AssemblyInfo.cs b/Torch.Server/Properties/AssemblyInfo.cs index cd9dab5..f623ac6 100644 --- a/Torch.Server/Properties/AssemblyInfo.cs +++ b/Torch.Server/Properties/AssemblyInfo.cs @@ -1,4 +1,4 @@ using System.Reflection; -[assembly: AssemblyVersion("1.0.168.389")] -[assembly: AssemblyFileVersion("1.0.168.389")] \ No newline at end of file +[assembly: AssemblyVersion("1.0.169.376")] +[assembly: AssemblyFileVersion("1.0.169.376")] \ No newline at end of file diff --git a/Torch.Server/Torch.Server.csproj b/Torch.Server/Torch.Server.csproj index 8f574bb..2ea886a 100644 --- a/Torch.Server/Torch.Server.csproj +++ b/Torch.Server/Torch.Server.csproj @@ -51,10 +51,12 @@ False ..\GameBinaries\Microsoft.CodeAnalysis.dll + False False ..\GameBinaries\Microsoft.CodeAnalysis.CSharp.dll + False ..\packages\NLog.4.4.1\lib\net45\NLog.dll @@ -63,30 +65,37 @@ False ..\GameBinaries\Sandbox.Common.dll + False False ..\GameBinaries\Sandbox.Game.dll + False False ..\GameBinaries\Sandbox.Graphics.dll + False False ..\GameBinaries\SpaceEngineers.Game.dll + False False ..\GameBinaries\SpaceEngineers.ObjectBuilders.dll + False False ..\GameBinaries\SpaceEngineers.ObjectBuilders.XmlSerializers.dll + False False ..\GameBinaries\SteamSDK.dll + False @@ -107,6 +116,7 @@ False ..\GameBinaries\VRage.dll + False False @@ -115,53 +125,64 @@ False ..\GameBinaries\VRage.Dedicated.dll + False False ..\GameBinaries\VRage.Game.dll + False False ..\GameBinaries\VRage.Game.XmlSerializers.dll + False False ..\GameBinaries\VRage.Input.dll + False False ..\GameBinaries\VRage.Library.dll + False False ..\GameBinaries\VRage.Math.dll + False False ..\GameBinaries\VRage.Native.dll + False False ..\GameBinaries\VRage.OpenVRWrapper.dll + False False ..\GameBinaries\VRage.Render.dll + False False ..\GameBinaries\VRage.Render11.dll + False False ..\GameBinaries\VRage.Scripting.dll + False - + @@ -171,6 +192,7 @@ + Component @@ -187,6 +209,7 @@ + diff --git a/Torch/TorchConfig.cs b/Torch.Server/TorchConfig.cs similarity index 95% rename from Torch/TorchConfig.cs rename to Torch.Server/TorchConfig.cs index d3408bf..43843b0 100644 --- a/Torch/TorchConfig.cs +++ b/Torch.Server/TorchConfig.cs @@ -1,15 +1,11 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using System.Windows; using System.Xml.Serialization; using NLog; -using Sandbox.ModAPI.Ingame; -namespace Torch +namespace Torch.Server { public class TorchConfig : ITorchConfig { diff --git a/Torch.Server/TorchServer.cs b/Torch.Server/TorchServer.cs index d62e0ec..6d39984 100644 --- a/Torch.Server/TorchServer.cs +++ b/Torch.Server/TorchServer.cs @@ -9,12 +9,10 @@ using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Security.Principal; -using System.Text; using System.Threading; -using Havok; using Microsoft.Xml.Serialization.GeneratedAssembly; -using Sandbox.Game.Entities.Cube; using Sandbox.Game.Multiplayer; +using Sandbox.ModAPI; using SteamSDK; using Torch.API; using VRage.Dedicated; @@ -25,8 +23,8 @@ using VRage.Game.SessionComponents; using VRage.Library; using VRage.ObjectBuilders; using VRage.Plugins; -using VRage.Trace; using VRage.Utils; +#pragma warning disable 618 namespace Torch.Server { @@ -44,6 +42,7 @@ namespace Torch.Server private TimeSpan _elapsedPlayTime; private float _simRatio; private readonly AutoResetEvent _stopHandle = new AutoResetEvent(false); + private Timer _watchdog; public TorchServer(TorchConfig config = null) { @@ -171,6 +170,27 @@ namespace Torch.Server base.Update(); SimulationRatio = Sync.ServerSimulationRatio; ElapsedPlayTime = MySession.Static?.ElapsedPlayTime ?? default(TimeSpan); + + if (_watchdog == null) + { + Log.Info("Starting server watchdog."); + _watchdog = new Timer(CheckServerResponding, this, TimeSpan.Zero, TimeSpan.FromSeconds(30)); + } + } + + private static void CheckServerResponding(object state) + { + var mre = new ManualResetEvent(false); + ((TorchServer)state).Invoke(() => mre.Set()); + if (!mre.WaitOne(TimeSpan.FromSeconds(30))) + { + var mainThread = MySandboxGame.Static.UpdateThread; + mainThread.Suspend(); + var stackTrace = new StackTrace(mainThread, true); + throw new TimeoutException($"Server watchdog detected that the server was frozen for at least 30 seconds.\n{stackTrace}"); + } + + Log.Debug("Server watchdog responded"); } /// diff --git a/Torch.Server/ViewModels/ConfigDedicatedViewModel.cs b/Torch.Server/ViewModels/ConfigDedicatedViewModel.cs index 7890a64..0414e3b 100644 --- a/Torch.Server/ViewModels/ConfigDedicatedViewModel.cs +++ b/Torch.Server/ViewModels/ConfigDedicatedViewModel.cs @@ -4,6 +4,7 @@ using System.Collections.ObjectModel; using System.Linq; using System.Text; using System.Threading.Tasks; +using NLog; using Sandbox.Engine.Utils; using VRage.Game; using VRage.Game.ModAPI; @@ -12,6 +13,7 @@ namespace Torch.Server.ViewModels { public class ConfigDedicatedViewModel : ViewModel { + private static readonly Logger Log = LogManager.GetLogger("Config"); private MyConfigDedicated _config; public ConfigDedicatedViewModel() : this(new MyConfigDedicated("")) @@ -42,7 +44,12 @@ namespace Torch.Server.ViewModels _config.Mods.Clear(); foreach (var mod in Mods.Split(newline, StringSplitOptions.RemoveEmptyEntries)) - _config.Mods.Add(ulong.Parse(mod)); + { + if (ulong.TryParse(mod, out ulong modId)) + _config.Mods.Add(modId); + else + Log.Warn($"'{mod}' is not a valid mod ID."); + } _config.Save(path); } diff --git a/Torch.Server/ViewModels/Entities/Blocks/BlockViewModel.cs b/Torch.Server/ViewModels/Entities/Blocks/BlockViewModel.cs index 57f2cad..56aa4ed 100644 --- a/Torch.Server/ViewModels/Entities/Blocks/BlockViewModel.cs +++ b/Torch.Server/ViewModels/Entities/Blocks/BlockViewModel.cs @@ -47,6 +47,9 @@ namespace Torch.Server.ViewModels.Blocks public BlockViewModel(IMyTerminalBlock block, EntityTreeViewModel tree) : base(block, tree) { Block = block; + if (Block == null) + return; + var propList = new List(); block.GetProperties(propList); foreach (var prop in propList) diff --git a/Torch.Server/ViewModels/Entities/GridViewModel.cs b/Torch.Server/ViewModels/Entities/GridViewModel.cs index 1ed0e62..3dd5363 100644 --- a/Torch.Server/ViewModels/Entities/GridViewModel.cs +++ b/Torch.Server/ViewModels/Entities/GridViewModel.cs @@ -1,14 +1,16 @@ using System.Linq; +using NLog; using Sandbox.Game.Entities; using Sandbox.ModAPI; using Torch.Server.ViewModels.Blocks; namespace Torch.Server.ViewModels.Entities { - public class GridViewModel : EntityViewModel + public class GridViewModel : EntityViewModel, ILazyLoad { private MyCubeGrid Grid => (MyCubeGrid)Entity; public MTObservableCollection Blocks { get; } = new MTObservableCollection(); + private static readonly Logger Log = LogManager.GetLogger(nameof(GridViewModel)); /// public string DescriptiveName => $"{Name} ({Grid.BlocksCount} blocks)"; @@ -17,17 +19,8 @@ namespace Torch.Server.ViewModels.Entities public GridViewModel(MyCubeGrid grid, EntityTreeViewModel tree) : base(grid, tree) { - TorchBase.Instance.InvokeBlocking(() => - { - foreach (var block in grid.GetFatBlocks().Where(b => b is IMyTerminalBlock)) - { - Blocks.Add(new BlockViewModel((IMyTerminalBlock)block, tree)); - } - }); - Blocks.Sort(b => b.Block.GetType().AssemblyQualifiedName); - - grid.OnBlockAdded += Grid_OnBlockAdded; - grid.OnBlockRemoved += Grid_OnBlockRemoved; + Log.Debug($"Creating model {Grid.DisplayName}"); + Blocks.Add(new BlockViewModel(null, Tree)); } private void Grid_OnBlockRemoved(Sandbox.Game.Entities.Cube.MySlimBlock obj) @@ -48,5 +41,27 @@ namespace Torch.Server.ViewModels.Entities Blocks.Sort(b => b.Block.GetType().AssemblyQualifiedName); OnPropertyChanged(nameof(Name)); } + + private bool _load; + public void Load() + { + if (_load) + return; + + Log.Debug($"Loading model {Grid.DisplayName}"); + _load = true; + Blocks.Clear(); + TorchBase.Instance.InvokeBlocking(() => + { + foreach (var block in Grid.GetFatBlocks().Where(b => b is IMyTerminalBlock)) + { + Blocks.Add(new BlockViewModel((IMyTerminalBlock)block, Tree)); + } + }); + Blocks.Sort(b => b.Block.GetType().AssemblyQualifiedName); + + Grid.OnBlockAdded += Grid_OnBlockAdded; + Grid.OnBlockRemoved += Grid_OnBlockRemoved; + } } } diff --git a/Torch.Server/ViewModels/Entities/VoxelMapViewModel.cs b/Torch.Server/ViewModels/Entities/VoxelMapViewModel.cs index 9809214..e1f5384 100644 --- a/Torch.Server/ViewModels/Entities/VoxelMapViewModel.cs +++ b/Torch.Server/ViewModels/Entities/VoxelMapViewModel.cs @@ -3,7 +3,6 @@ using System.Linq; using Sandbox.Game.Entities; using VRage.Game.Entity; using VRage.Game.ModAPI; -using VRage.Library.Collections; namespace Torch.Server.ViewModels.Entities { @@ -11,7 +10,7 @@ namespace Torch.Server.ViewModels.Entities { private MyVoxelBase Voxel => (MyVoxelBase)Entity; - public override string Name => Voxel.StorageName; + public override string Name => string.IsNullOrEmpty(Voxel.StorageName) ? "Unnamed" : Voxel.StorageName; public override bool CanStop => false; @@ -19,6 +18,9 @@ namespace Torch.Server.ViewModels.Entities public void UpdateAttachedGrids() { + //TODO: fix + return; + AttachedGrids.Clear(); var box = Entity.WorldAABB; var entities = new List(); diff --git a/Torch.Server/ViewModels/ILazyLoad.cs b/Torch.Server/ViewModels/ILazyLoad.cs new file mode 100644 index 0000000..526b03d --- /dev/null +++ b/Torch.Server/ViewModels/ILazyLoad.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Torch.Server.ViewModels +{ + public interface ILazyLoad + { + void Load(); + } +} diff --git a/Torch.Server/ViewModels/PluginManagerViewModel.cs b/Torch.Server/ViewModels/PluginManagerViewModel.cs index 06196f0..d6e7aa1 100644 --- a/Torch.Server/ViewModels/PluginManagerViewModel.cs +++ b/Torch.Server/ViewModels/PluginManagerViewModel.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using Torch.API; +using Torch.API.Managers; using Torch.API.Plugins; namespace Torch.Server.ViewModels @@ -15,7 +16,7 @@ namespace Torch.Server.ViewModels private PluginViewModel _selectedPlugin; public PluginViewModel SelectedPlugin { - get { return _selectedPlugin; } + get => _selectedPlugin; set { _selectedPlugin = value; OnPropertyChanged(); } } diff --git a/Torch.Server/ViewModels/SteamUserViewModel.cs b/Torch.Server/ViewModels/SteamUserViewModel.cs index 2a9e1a3..87d4987 100644 --- a/Torch.Server/ViewModels/SteamUserViewModel.cs +++ b/Torch.Server/ViewModels/SteamUserViewModel.cs @@ -9,26 +9,13 @@ namespace Torch.Server.ViewModels { public class SteamUserViewModel : ViewModel { - private string _name; - public string Name { get => _name; set { } } - - private ulong _id; - - public ulong SteamId - { - get => _id; - set - { - _id = value; - OnPropertyChanged(); - //TODO: resolve user name - OnPropertyChanged(nameof(Name)); - } - } + public string Name { get; } + public ulong SteamId { get; } public SteamUserViewModel(ulong id) { SteamId = id; + Name = SteamAPI.Instance.Friends.GetPersonaName(id); } public SteamUserViewModel() : this(0) { } diff --git a/Torch.Server/Views/ChatControl.xaml b/Torch.Server/Views/ChatControl.xaml index c52cd67..a9186c4 100644 --- a/Torch.Server/Views/ChatControl.xaml +++ b/Torch.Server/Views/ChatControl.xaml @@ -10,7 +10,7 @@ - + diff --git a/Torch.Server/Views/ChatControl.xaml.cs b/Torch.Server/Views/ChatControl.xaml.cs index fcc2eab..32c6755 100644 --- a/Torch.Server/Views/ChatControl.xaml.cs +++ b/Torch.Server/Views/ChatControl.xaml.cs @@ -19,6 +19,7 @@ using Sandbox.Engine.Multiplayer; using Sandbox.Game.World; using SteamSDK; using Torch.API; +using Torch.Managers; namespace Torch.Server { @@ -27,7 +28,8 @@ namespace Torch.Server /// public partial class ChatControl : UserControl { - private ITorchServer _server; + private TorchBase _server; + private MultiplayerManager _multiplayer; public ChatControl() { @@ -36,17 +38,9 @@ namespace Torch.Server public void BindServer(ITorchServer server) { - _server = server; - server.Multiplayer.MessageReceived += Refresh; - } - - private void Refresh(IChatMessage chatItem, ref bool sendToOthers) - { - Dispatcher.Invoke(() => - { - ChatItems.ItemsSource = null; - ChatItems.ItemsSource = _server.Multiplayer.ChatHistory; - }); + _server = (TorchBase)server; + _multiplayer = (MultiplayerManager)server.Multiplayer; + DataContext = _multiplayer; } private void SendButton_Click(object sender, RoutedEventArgs e) @@ -64,11 +58,11 @@ namespace Torch.Server { //Can't use Message.Text directly because of object ownership in WPF. var text = Message.Text; - var commands = ((TorchBase)_server).Commands; + var commands = _server.Commands; string response = null; if (commands.IsCommand(text)) { - _server.Multiplayer.ChatHistory.Add(new ChatMessage(DateTime.Now, 0, "Server", text)); + _multiplayer.ChatHistory.Add(new ChatMessage(DateTime.Now, 0, "Server", text)); _server.InvokeBlocking(() => { response = commands.HandleCommandFromServer(text); @@ -79,10 +73,8 @@ namespace Torch.Server _server.Multiplayer.SendMessage(text); } if (!string.IsNullOrEmpty(response)) - _server.Multiplayer.ChatHistory.Add(new ChatMessage(DateTime.Now, 0, "Server", response)); + _multiplayer.ChatHistory.Add(new ChatMessage(DateTime.Now, 0, "Server", response)); Message.Text = ""; - var sto = false; - Refresh(null, ref sto); } } } diff --git a/Torch.Server/Views/ConfigControl.xaml.cs b/Torch.Server/Views/ConfigControl.xaml.cs index 7f705df..54f15e7 100644 --- a/Torch.Server/Views/ConfigControl.xaml.cs +++ b/Torch.Server/Views/ConfigControl.xaml.cs @@ -52,7 +52,13 @@ namespace Torch.Server.Views Log.Info("Saved DS config."); try { - var checkpoint = MyLocalCache.LoadCheckpoint(Config.LoadWorld, out _); + //var checkpoint = MyLocalCache.LoadCheckpoint(Config.LoadWorld, out _); + MyObjectBuilderSerializer.DeserializeXML(Path.Combine(Config.LoadWorld, "Sandbox.sbc"), out MyObjectBuilder_Checkpoint checkpoint, out ulong sizeInBytes); + if (checkpoint == null) + { + Log.Error($"Failed to load {Config.LoadWorld}, checkpoint null ({sizeInBytes} bytes, instance {TorchBase.Instance.Config.InstancePath})"); + return; + } checkpoint.Settings = Config.SessionSettings; checkpoint.Mods.Clear(); foreach (var modId in Config.Mods) @@ -75,6 +81,7 @@ namespace Torch.Server.Views if (!File.Exists(path)) { + Log.Error($"Failed to load dedicated config at {path}"); DataContext = null; return; } diff --git a/Torch.Server/Views/EntitiesControl.xaml b/Torch.Server/Views/EntitiesControl.xaml index 6bff35f..2a78722 100644 --- a/Torch.Server/Views/EntitiesControl.xaml +++ b/Torch.Server/Views/EntitiesControl.xaml @@ -18,7 +18,7 @@ Margin="3" />