Refactor stuff, clean up managers

This commit is contained in:
John Gross
2017-06-24 17:25:22 -07:00
parent 4962c753cd
commit 4b4a069adb
51 changed files with 607 additions and 450 deletions

View File

@@ -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!");
}
}
}

View File

@@ -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
{
/// <inheritdoc />
public override void Init(ITorchBase torch)
{
base.Init(torch);
//Torch.Log.Write($"Plugin init {Name}");
}
/// <inheritdoc />
public override void Update()
{
//Torch.Log.Write($"Plugin update {Name}");
}
/// <inheritdoc />
public override void Dispose()
{
//Torch.Log.Write($"Plugin unload {Name}");
}
}
}

View File

@@ -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")]

View File

@@ -1,70 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{ABD18A6C-F638-44E9-8E55-DEDEA321C600}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>TestPlugin</RootNamespace>
<AssemblyName>TestPlugin</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="Sandbox.Game">
<HintPath>..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\Sandbox.Game.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
<Reference Include="VRage">
<HintPath>..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.dll</HintPath>
</Reference>
<Reference Include="VRage.Game, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.Game.dll</HintPath>
</Reference>
<Reference Include="VRage.Math, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</ItemGroup>
<ItemGroup>
<Compile Include="Commands.cs" />
<Compile Include="Plugin.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Torch.API\Torch.API.csproj">
<Project>{FBA5D932-6254-4A1E-BAF4-E229FA94E3C2}</Project>
<Name>Torch.API</Name>
</ProjectReference>
<ProjectReference Include="..\Torch\Torch.csproj">
<Project>{7e01635c-3b67-472e-bcd6-c5539564f214}</Project>
<Name>Torch</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

16
Torch.API/IPlayer.cs Normal file
View File

@@ -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; }
}
}

View File

@@ -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<T>() where T : class, IManager;
}
public interface ITorchServer : ITorchBase

View File

@@ -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();
}
}

View File

@@ -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<ulong> PlayerJoined;
event Action<ulong, ConnectionState> PlayerLeft;
event Action<IPlayer> PlayerJoined;
event Action<IPlayer> 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<IChatMessage> ChatHistory { get; }
}
}

View File

@@ -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);
}
}

View File

@@ -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<ITorchPlugin>
public interface IPluginManager : IManager, IEnumerable<ITorchPlugin>
{
event Action<List<ITorchPlugin>> PluginsLoaded;
List<ITorchPlugin> Plugins { get; }
void UpdatePlugins();
void Init();
void DisposePlugins();
}
}

View File

@@ -35,6 +35,7 @@
<Reference Include="HavokWrapper, Version=1.0.6278.22649, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\HavokWrapper.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="NLog">
<HintPath>..\packages\NLog.4.4.1\lib\net45\NLog.dll</HintPath>
@@ -45,30 +46,37 @@
<Reference Include="Sandbox.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\Sandbox.Common.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Sandbox.Game, Version=0.1.6305.30774, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\Sandbox.Game.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Sandbox.Graphics, Version=0.1.6305.30761, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\Sandbox.Graphics.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="SpaceEngineers.Game, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\SpaceEngineers.Game.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="SpaceEngineers.ObjectBuilders, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\SpaceEngineers.ObjectBuilders.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="SpaceEngineers.ObjectBuilders.XmlSerializers, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\SpaceEngineers.ObjectBuilders.XmlSerializers.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="SteamSDK, Version=0.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\SteamSDK.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />
@@ -85,59 +93,75 @@
<Reference Include="System.Xml" />
<Reference Include="VRage">
<HintPath>..\GameBinaries\VRage.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Audio, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.Audio.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Dedicated">
<HintPath>..\GameBinaries\VRage.Dedicated.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Game, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.Game.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Game.XmlSerializers, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.Game.XmlSerializers.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Input, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.Input.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Library">
<HintPath>..\GameBinaries\VRage.Library.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Math, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.Math.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Native, Version=0.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.Native.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.OpenVRWrapper, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.OpenVRWrapper.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Render, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.Render.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Render11, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.Render11.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Scripting, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.Scripting.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="ConnectionState.cs" />
<Compile Include="IChatMessage.cs" />
<Compile Include="IMultiplayer.cs" />
<Compile Include="IPluginManager.cs" />
<Compile Include="Managers\IManager.cs" />
<Compile Include="Managers\IMultiplayerManager.cs" />
<Compile Include="IPlayer.cs" />
<Compile Include="Managers\INetworkManager.cs" />
<Compile Include="Managers\IPluginManager.cs" />
<Compile Include="ITorchConfig.cs" />
<Compile Include="Plugins\ITorchPlugin.cs" />
<Compile Include="IServerControls.cs" />

View File

@@ -1,4 +1,4 @@
using System.Reflection;
[assembly: AssemblyVersion("1.0.168.389")]
[assembly: AssemblyFileVersion("1.0.168.389")]
[assembly: AssemblyVersion("1.0.169.376")]
[assembly: AssemblyFileVersion("1.0.169.376")]

View File

@@ -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);

View File

@@ -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)
{
}
/// <inheritdoc />
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<MyObjectBuilder_SessionSettings>(configPath);
config.Load();
DedicatedConfig = new ConfigDedicatedViewModel(config);
}
/// <summary>
/// Creates a skeleton of a DS instance folder at the given directory.
/// </summary>
/// <param name="path"></param>
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);
}
}
}

View File

@@ -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.
}
/// <summary>
/// Creates a skeleton of a DS instance folder at the given directory.
/// </summary>
/// <param name="path"></param>
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);
}
}
}

View File

@@ -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
{

View File

@@ -1,4 +1,4 @@
using System.Reflection;
[assembly: AssemblyVersion("1.0.168.389")]
[assembly: AssemblyFileVersion("1.0.168.389")]
[assembly: AssemblyVersion("1.0.169.376")]
[assembly: AssemblyFileVersion("1.0.169.376")]

View File

@@ -51,10 +51,12 @@
<Reference Include="Microsoft.CodeAnalysis, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\Microsoft.CodeAnalysis.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.CodeAnalysis.CSharp, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\Microsoft.CodeAnalysis.CSharp.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<HintPath>..\packages\NLog.4.4.1\lib\net45\NLog.dll</HintPath>
@@ -63,30 +65,37 @@
<Reference Include="Sandbox.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\Sandbox.Common.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Sandbox.Game, Version=0.1.6305.30774, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\Sandbox.Game.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Sandbox.Graphics, Version=0.1.6305.30761, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\Sandbox.Graphics.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="SpaceEngineers.Game, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\SpaceEngineers.Game.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="SpaceEngineers.ObjectBuilders, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\SpaceEngineers.ObjectBuilders.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="SpaceEngineers.ObjectBuilders.XmlSerializers, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\SpaceEngineers.ObjectBuilders.XmlSerializers.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="SteamSDK, Version=0.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\SteamSDK.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration.Install" />
@@ -107,6 +116,7 @@
<Reference Include="VRage, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Audio, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
@@ -115,53 +125,64 @@
<Reference Include="VRage.Dedicated, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.Dedicated.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Game, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.Game.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Game.XmlSerializers, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.Game.XmlSerializers.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Input, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.Input.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Library, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.Library.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Math, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.Math.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Native, Version=0.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.Native.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.OpenVRWrapper, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.OpenVRWrapper.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Render, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.Render.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Render11, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.Render11.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Scripting, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.Scripting.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<Compile Include="Managers\DSConfigManager.cs" />
<Compile Include="Managers\ConfigManager.cs" />
<Compile Include="TorchCli.cs" />
<Compile Include="NativeMethods.cs" />
<Compile Include="Properties\AssemblyInfo.cs">
@@ -171,6 +192,7 @@
</Compile>
<Compile Include="Properties\AssemblyInfo1.cs" />
<Compile Include="ServerStatistics.cs" />
<Compile Include="TorchConfig.cs" />
<Compile Include="TorchService.cs">
<SubType>Component</SubType>
</Compile>
@@ -187,6 +209,7 @@
<Compile Include="ViewModels\Entities\EntityViewModel.cs" />
<Compile Include="ViewModels\Entities\FloatingObjectViewModel.cs" />
<Compile Include="ViewModels\Entities\GridViewModel.cs" />
<Compile Include="ViewModels\ILazyLoad.cs" />
<Compile Include="ViewModels\PluginManagerViewModel.cs" />
<Compile Include="ViewModels\PluginViewModel.cs" />
<Compile Include="ViewModels\SessionSettingsViewModel.cs" />

View File

@@ -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
{

View File

@@ -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");
}
/// <summary>

View File

@@ -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<MyObjectBuilder_SessionSettings> _config;
public ConfigDedicatedViewModel() : this(new MyConfigDedicated<MyObjectBuilder_SessionSettings>(""))
@@ -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);
}

View File

@@ -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<ITerminalProperty>();
block.GetProperties(propList);
foreach (var prop in propList)

View File

@@ -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<BlockViewModel> Blocks { get; } = new MTObservableCollection<BlockViewModel>();
private static readonly Logger Log = LogManager.GetLogger(nameof(GridViewModel));
/// <inheritdoc />
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;
}
}
}

View File

@@ -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<MyEntity>();

View File

@@ -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();
}
}

View File

@@ -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(); }
}

View File

@@ -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) { }

View File

@@ -10,7 +10,7 @@
<Button x:Name="Send" Content="Send" DockPanel.Dock="Right" Width="50" Margin="5,5,5,5" Click="SendButton_Click"></Button>
<TextBox x:Name="Message" DockPanel.Dock="Left" Margin="5,5,5,5" KeyDown="Message_OnKeyDown"></TextBox>
</DockPanel>
<ListView x:Name="ChatItems" Margin="5,5,5,5">
<ListView x:Name="ChatItems" ItemsSource="{Binding ChatHistory}" Margin="5,5,5,5">
<ListView.ItemTemplate>
<DataTemplate>
<WrapPanel>

View File

@@ -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
/// </summary>
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);
}
}
}

View File

@@ -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;
}

View File

@@ -18,7 +18,7 @@
Margin="3" />
<Button Content="Stop" Click="Stop_OnClick" IsEnabled="{Binding CurrentEntity.CanStop}" Margin="3" />
</StackPanel>
<TreeView Width="300" Margin="3" DockPanel.Dock="Top" SelectedItemChanged="TreeView_OnSelectedItemChanged">
<TreeView Width="300" Margin="3" DockPanel.Dock="Top" SelectedItemChanged="TreeView_OnSelectedItemChanged" TreeViewItem.Expanded="TreeViewItem_OnExpanded">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type entities:GridViewModel}" ItemsSource="{Binding Blocks}">
<TextBlock Text="{Binding DescriptiveName}" />
@@ -30,12 +30,12 @@
<TextBlock Text="{Binding Name}"/>
</HierarchicalDataTemplate>
</TreeView.Resources>
<TreeViewItem ItemsSource="{Binding Grids}" IsExpanded="true">
<TreeViewItem ItemsSource="{Binding Grids}">
<TreeViewItem.Header>
<TextBlock Text="{Binding Grids.Count, StringFormat=Grids ({0})}" />
</TreeViewItem.Header>
</TreeViewItem>
<TreeViewItem ItemsSource="{Binding Characters}" IsExpanded="true">
<TreeViewItem ItemsSource="{Binding Characters}">
<TreeViewItem.Header>
<TextBlock Text="{Binding Characters.Count, StringFormat=Characters ({0})}" />
</TreeViewItem.Header>
@@ -45,7 +45,7 @@
</DataTemplate>
</TreeViewItem.ItemTemplate>
</TreeViewItem>
<TreeViewItem ItemsSource="{Binding VoxelMaps}" IsExpanded="true">
<TreeViewItem ItemsSource="{Binding VoxelMaps}">
<TreeViewItem.Header>
<TextBlock Text="{Binding VoxelMaps.Count, StringFormat=Voxel Maps ({0})}" />
</TreeViewItem.Header>
@@ -55,7 +55,7 @@
</DataTemplate>
</TreeViewItem.ItemTemplate>
</TreeViewItem>
<TreeViewItem ItemsSource="{Binding FloatingObjects}" IsExpanded="true">
<TreeViewItem ItemsSource="{Binding FloatingObjects}">
<TreeViewItem.Header>
<TextBlock Text="{Binding FloatingObjects.Count, StringFormat=Floating Objects ({0})}" />
</TreeViewItem.Header>

View File

@@ -12,6 +12,7 @@ using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using NLog;
using Torch.Server.ViewModels;
using Torch.Server.ViewModels.Blocks;
using Torch.Server.ViewModels.Entities;
@@ -64,5 +65,13 @@ namespace Torch.Server.Views
{
TorchBase.Instance.Invoke(() => Entities.CurrentEntity?.Entity.Physics?.ClearSpeed());
}
private void TreeViewItem_OnExpanded(object sender, RoutedEventArgs e)
{
LogManager.GetLogger("EntitiesControl").Debug(nameof(TreeViewItem_OnExpanded));
var item = (TreeViewItem)e.Source;
if (item.DataContext is ILazyLoad l)
l.Load();
}
}
}

View File

@@ -5,10 +5,11 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Torch.Server.Views"
xmlns:torch="clr-namespace:Torch;assembly=Torch"
xmlns:server="clr-namespace:Torch.Server"
mc:Ignorable="d"
Title="Torch First Time Setup" Height="200" Width="500">
<Window.DataContext>
<torch:TorchConfig/>
<server:TorchConfig/>
</Window.DataContext>
<StackPanel>
<DockPanel ToolTip="This should be set to the folder that contains your mods and saves.">

View File

@@ -10,7 +10,7 @@
<Button x:Name="KickButton" Content="Kick" Margin="5,5,5,5" Click="KickButton_Click"/>
<Button x:Name="BanButton" Content="Ban" Margin="5,5,5,5" Click="BanButton_Click"/>
</StackPanel>
<ListView x:Name="PlayerList" DockPanel.Dock="Top" Margin="5,5,5,5">
<ListView x:Name="PlayerList" ItemsSource="{Binding Players}" DockPanel.Dock="Top" Margin="5,5,5,5">
<ListView.ItemTemplate>
<DataTemplate>
<WrapPanel>

View File

@@ -17,8 +17,10 @@ using Sandbox;
using Sandbox.Engine.Multiplayer;
using Sandbox.Game.Multiplayer;
using Sandbox.Game.World;
using Sandbox.ModAPI;
using SteamSDK;
using Torch.API;
using Torch.Managers;
using VRage.Game.ModAPI;
namespace Torch.Server
@@ -38,18 +40,7 @@ namespace Torch.Server
public void BindServer(ITorchServer server)
{
_server = server;
//server.Multiplayer.PlayerJoined += Refresh;
//server.Multiplayer.PlayerLeft += Refresh;
Refresh();
}
private void Refresh(IMyPlayer player = null)
{
Dispatcher.Invoke(() =>
{
PlayerList.ItemsSource = null;
//PlayerList.ItemsSource = _server.Multiplayer.Players;
});
DataContext = (MultiplayerManager)_server.Multiplayer;
}
private void KickButton_Click(object sender, RoutedEventArgs e)

View File

@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26127.3
VisualStudioVersion = 15.0.26430.14
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Torch", "Torch\Torch.csproj", "{7E01635C-3B67-472E-BCD6-C5539564F214}"
EndProject
@@ -20,40 +20,28 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7E01635C-3B67-472E-BCD6-C5539564F214}.Debug|Any CPU.ActiveCfg = Debug|x64
{7E01635C-3B67-472E-BCD6-C5539564F214}.Debug|x64.ActiveCfg = Debug|x64
{7E01635C-3B67-472E-BCD6-C5539564F214}.Debug|x64.Build.0 = Debug|x64
{7E01635C-3B67-472E-BCD6-C5539564F214}.Release|Any CPU.ActiveCfg = Release|x64
{7E01635C-3B67-472E-BCD6-C5539564F214}.Release|x64.ActiveCfg = Release|x64
{7E01635C-3B67-472E-BCD6-C5539564F214}.Release|x64.Build.0 = Release|x64
{FBA5D932-6254-4A1E-BAF4-E229FA94E3C2}.Debug|Any CPU.ActiveCfg = Debug|x64
{FBA5D932-6254-4A1E-BAF4-E229FA94E3C2}.Debug|x64.ActiveCfg = Debug|x64
{FBA5D932-6254-4A1E-BAF4-E229FA94E3C2}.Debug|x64.Build.0 = Debug|x64
{FBA5D932-6254-4A1E-BAF4-E229FA94E3C2}.Release|Any CPU.ActiveCfg = Release|x64
{FBA5D932-6254-4A1E-BAF4-E229FA94E3C2}.Release|x64.ActiveCfg = Release|x64
{FBA5D932-6254-4A1E-BAF4-E229FA94E3C2}.Release|x64.Build.0 = Release|x64
{E36DF745-260B-4956-A2E8-09F08B2E7161}.Debug|Any CPU.ActiveCfg = Debug|x64
{E36DF745-260B-4956-A2E8-09F08B2E7161}.Debug|x64.ActiveCfg = Debug|x64
{E36DF745-260B-4956-A2E8-09F08B2E7161}.Debug|x64.Build.0 = Debug|x64
{E36DF745-260B-4956-A2E8-09F08B2E7161}.Release|Any CPU.ActiveCfg = Release|x64
{E36DF745-260B-4956-A2E8-09F08B2E7161}.Release|x64.ActiveCfg = Release|x64
{E36DF745-260B-4956-A2E8-09F08B2E7161}.Release|x64.Build.0 = Release|x64
{CA50886B-7B22-4CD8-93A0-C06F38D4F77D}.Debug|Any CPU.ActiveCfg = Debug|x64
{CA50886B-7B22-4CD8-93A0-C06F38D4F77D}.Debug|x64.ActiveCfg = Debug|x64
{CA50886B-7B22-4CD8-93A0-C06F38D4F77D}.Debug|x64.Build.0 = Debug|x64
{CA50886B-7B22-4CD8-93A0-C06F38D4F77D}.Release|Any CPU.ActiveCfg = Release|x64
{CA50886B-7B22-4CD8-93A0-C06F38D4F77D}.Release|x64.ActiveCfg = Release|x64
{CA50886B-7B22-4CD8-93A0-C06F38D4F77D}.Release|x64.Build.0 = Release|x64
{19292801-5B9C-4EE0-961F-0FA37B3A6C3D}.Debug|Any CPU.ActiveCfg = Debug|x64
{19292801-5B9C-4EE0-961F-0FA37B3A6C3D}.Debug|x64.ActiveCfg = Debug|x64
{19292801-5B9C-4EE0-961F-0FA37B3A6C3D}.Debug|x64.Build.0 = Debug|x64
{19292801-5B9C-4EE0-961F-0FA37B3A6C3D}.Release|Any CPU.ActiveCfg = Release|x64
{19292801-5B9C-4EE0-961F-0FA37B3A6C3D}.Release|x64.ActiveCfg = Release|x64
{19292801-5B9C-4EE0-961F-0FA37B3A6C3D}.Release|x64.Build.0 = Release|x64
EndGlobalSection

View File

@@ -3,31 +3,31 @@ using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace Torch
{
public class CommandLine
{
private readonly string _argPrefix;
private readonly Dictionary<ArgAttribute, PropertyInfo> _args = new Dictionary<ArgAttribute, PropertyInfo>();
public CommandLine(string argPrefix = "-")
{
_argPrefix = argPrefix;
}
public PropertyInfo[] GetArgs()
{
return GetType().GetProperties().Where(p => p.HasAttribute<ArgAttribute>()).ToArray();
foreach (var prop in GetType().GetProperties())
{
if (prop.HasAttribute<ArgAttribute>())
_args.Add(prop.GetCustomAttribute<ArgAttribute>(), prop);
}
}
public string GetHelp()
{
var sb = new StringBuilder();
foreach (var property in GetArgs())
foreach (var property in _args)
{
var attr = property.GetCustomAttribute<ArgAttribute>();
var attr = property.Key;
sb.AppendLine($"{_argPrefix}{attr.Name.PadRight(24)}{attr.Description}");
}
@@ -37,16 +37,16 @@ namespace Torch
public override string ToString()
{
var args = new List<string>();
foreach (var prop in GetArgs())
foreach (var prop in _args)
{
var attr = prop.GetCustomAttribute<ArgAttribute>();
if (prop.PropertyType == typeof(bool) && (bool)prop.GetValue(this))
var attr = prop.Key;
if (prop.Value.PropertyType == typeof(bool) && (bool)prop.Value.GetValue(this))
{
args.Add($"{_argPrefix}{attr.Name}");
}
else if (prop.PropertyType == typeof(string))
else if (prop.Value.PropertyType == typeof(string))
{
var str = (string)prop.GetValue(this);
var str = (string)prop.Value.GetValue(this);
if (string.IsNullOrEmpty(str))
continue;
args.Add($"{_argPrefix}{attr.Name} \"{str}\"");
@@ -67,16 +67,14 @@ namespace Torch
return false;
}
var properties = GetArgs();
for (var i = 0; i < args.Length; i++)
{
if (!args[i].StartsWith(_argPrefix))
continue;
foreach (var property in properties)
foreach (var property in _args)
{
var argName = property.GetCustomAttribute<ArgAttribute>()?.Name;
var argName = property.Key.Name;
if (argName == null)
continue;
@@ -84,11 +82,11 @@ namespace Torch
{
if (string.Compare(argName, 0, args[i], 1, argName.Length, StringComparison.InvariantCultureIgnoreCase) == 0)
{
if (property.PropertyType == typeof(bool))
property.SetValue(this, true);
if (property.Value.PropertyType == typeof(bool))
property.Value.SetValue(this, true);
if (property.PropertyType == typeof(string))
property.SetValue(this, args[++i]);
if (property.Value.PropertyType == typeof(string))
property.Value.SetValue(this, args[++i]);
}
}
catch

View File

@@ -6,6 +6,7 @@ using System.Text.RegularExpressions;
using NLog;
using Sandbox.Game.World;
using Torch.API;
using Torch.API.Managers;
using Torch.API.Plugins;
using Torch.Managers;
using VRage.Game.ModAPI;
@@ -13,20 +14,22 @@ using VRage.Network;
namespace Torch.Commands
{
public class CommandManager
public class CommandManager : Manager
{
public char Prefix { get; set; }
public CommandTree Commands { get; set; } = new CommandTree();
private Logger _log = LogManager.GetLogger(nameof(CommandManager));
private readonly ITorchBase _torch;
public CommandManager(ITorchBase torch, char prefix = '/')
public CommandManager(ITorchBase torch, char prefix = '/') : base(torch)
{
_torch = torch;
Prefix = prefix;
ChatManager.Instance.MessageRecieved += HandleCommand;
}
public override void Init()
{
RegisterCommandModule(typeof(TorchCommands));
Torch.GetManager<ChatManager>().MessageRecieved += HandleCommand;
}
public bool HasPermission(ulong steamId, Command command)
@@ -77,7 +80,7 @@ namespace Torch.Commands
var splitArgs = Regex.Matches(argText, "(\"[^\"]+\"|\\S+)").Cast<Match>().Select(x => x.ToString().Replace("\"", "")).ToList();
_log.Trace($"Invoking {cmdPath} for server.");
var context = new CommandContext(_torch, command.Plugin, null, argText, splitArgs);
var context = new CommandContext(Torch, command.Plugin, null, argText, splitArgs);
if (command.TryInvoke(context))
_log.Info($"Server ran command '{message}'");
else
@@ -99,7 +102,7 @@ namespace Torch.Commands
sendToOthers = false;
var player = _torch.Multiplayer.GetPlayerBySteamId(steamId);
var player = Torch.Multiplayer.GetPlayerBySteamId(steamId);
if (player == null)
{
_log.Error($"Command {message} invoked by nonexistant player");
@@ -116,14 +119,14 @@ namespace Torch.Commands
if (!HasPermission(steamId, command))
{
_log.Info($"{player.DisplayName} tried to use command {cmdPath} without permission");
_torch.Multiplayer.SendMessage($"You need to be a {command.MinimumPromoteLevel} or higher to use that command.", playerId: player.IdentityId);
Torch.Multiplayer.SendMessage($"You need to be a {command.MinimumPromoteLevel} or higher to use that command.", playerId: player.IdentityId);
return;
}
var splitArgs = Regex.Matches(argText, "(\"[^\"]+\"|\\S+)").Cast<Match>().Select(x => x.ToString().Replace("\"", "")).ToList();
_log.Trace($"Invoking {cmdPath} for player {player.DisplayName}");
var context = new CommandContext(_torch, command.Plugin, player, argText, splitArgs);
_torch.Invoke(() =>
var context = new CommandContext(Torch, command.Plugin, player, argText, splitArgs);
Torch.Invoke(() =>
{
if (command.TryInvoke(context))
_log.Info($"Player {player.DisplayName} ran command '{message}'");

View File

@@ -13,27 +13,6 @@ namespace Torch.Commands
{
public class TorchCommands : CommandModule
{
#if DEBUG
[Command("fixit")]
public void Fixit()
{
Environment.Exit(0);
}
[Command("dbgcmd")]
public void Dbgcmd()
{
var commandManager = ((PluginManager)Context.Torch.Plugins).Commands;
Console.WriteLine(commandManager.Commands.GetTreeString());
}
#endif
[Command("crash", "Causes the server to crash for testing purposes")]
[Permission(MyPromoteLevel.Admin)]
public void Crash()
{
throw new Exception("Crash triggered by Torch command");
}
[Command("help", "Displays help for a command")]
public void Help()
{

View File

@@ -5,6 +5,8 @@ using System.Text;
using System.Threading.Tasks;
using NLog;
using Sandbox.Engine.Multiplayer;
using Torch.API;
using Torch.API.Managers;
using VRage;
using VRage.Library.Collections;
using VRage.Network;
@@ -13,9 +15,9 @@ using VRage.Utils;
namespace Torch.Managers
{
public class ChatManager
[Manager]
public class ChatManager : Manager
{
public static ChatManager Instance { get; } = new ChatManager();
private static Logger _log = LogManager.GetLogger(nameof(ChatManager));
public delegate void MessageRecievedDel(ChatMsg msg, ref bool sendToOthers);
@@ -25,11 +27,16 @@ namespace Torch.Managers
internal void RaiseMessageRecieved(ChatMsg msg, ref bool sendToOthers) =>
MessageRecieved?.Invoke(msg, ref sendToOthers);
public void Init()
public ChatManager(ITorchBase torchInstance) : base(torchInstance)
{
}
public override void Init()
{
try
{
NetworkManager.Instance.RegisterNetworkHandlers(new ChatIntercept());
Torch.GetManager<INetworkManager>().RegisterNetworkHandler(new ChatIntercept(this));
}
catch
{
@@ -45,43 +52,50 @@ namespace Torch.Managers
RaiseMessageRecieved(msg, ref sendToOthers);
}
}
internal class ChatIntercept : NetworkHandlerBase
{
private bool? _unitTestResult;
public override bool CanHandle(CallSite site)
internal class ChatIntercept : NetworkHandlerBase, INetworkHandler
{
if (site.MethodInfo.Name != "OnChatMessageRecieved")
return false;
private ChatManager _chatManager;
private bool? _unitTestResult;
if (_unitTestResult.HasValue)
return _unitTestResult.Value;
var parameters = site.MethodInfo.GetParameters();
if (parameters.Length != 1)
public ChatIntercept(ChatManager chatManager)
{
_unitTestResult = false;
return false;
_chatManager = chatManager;
}
if (parameters[0].ParameterType != typeof(ChatMsg))
_unitTestResult = false;
public override bool CanHandle(CallSite site)
{
if (site.MethodInfo.Name != "OnChatMessageRecieved")
return false;
_unitTestResult = true;
if (_unitTestResult.HasValue)
return _unitTestResult.Value;
return _unitTestResult.Value;
}
var parameters = site.MethodInfo.GetParameters();
if (parameters.Length != 1)
{
_unitTestResult = false;
return false;
}
public override bool Handle(ulong remoteUserId, CallSite site, BitStream stream, object obj, MyPacket packet)
{
var msg = new ChatMsg();
Serialize(site.MethodInfo, stream, ref msg);
if (parameters[0].ParameterType != typeof(ChatMsg))
_unitTestResult = false;
bool sendToOthers = true;
ChatManager.Instance.RaiseMessageRecieved(msg, ref sendToOthers);
_unitTestResult = true;
return !sendToOthers;
return _unitTestResult.Value;
}
public override bool Handle(ulong remoteUserId, CallSite site, BitStream stream, object obj, MyPacket packet)
{
var msg = new ChatMsg();
Serialize(site.MethodInfo, stream, ref msg);
bool sendToOthers = true;
_chatManager.RaiseMessageRecieved(msg, ref sendToOthers);
return !sendToOthers;
}
}
}
}

View File

@@ -17,6 +17,7 @@ using Sandbox.ModAPI;
using SpaceEngineers.Game.Entities.Blocks;
using SpaceEngineers.Game.ModAPI;
using Torch.API;
using Torch.API.Managers;
using Torch.API.Plugins;
using VRage;
using VRage.Collections;
@@ -31,14 +32,13 @@ using VRageMath;
namespace Torch.Managers
{
public class EntityManager
public class EntityManager : Manager
{
private readonly ITorchBase _torch;
private static readonly Logger Log = LogManager.GetLogger(nameof(EntityManager));
public EntityManager(ITorchBase torch)
public EntityManager(ITorchBase torch) : base(torch)
{
_torch = torch;
}
public void ExportGrid(IMyCubeGrid grid, string path)

31
Torch/Managers/Manager.cs Normal file
View File

@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Torch.API;
using Torch.API.Managers;
namespace Torch.Managers
{
[AttributeUsage(AttributeTargets.Class)]
public class ManagerAttribute : Attribute
{
}
public abstract class Manager : IManager
{
protected ITorchBase Torch { get; }
protected Manager(ITorchBase torchInstance)
{
Torch = torchInstance;
}
public virtual void Init()
{
}
}
}

View File

@@ -19,8 +19,11 @@ using Sandbox.Engine.Multiplayer;
using Sandbox.Game.Multiplayer;
using Sandbox.Game.World;
using Sandbox.ModAPI;
using SharpDX.Toolkit.Collections;
using SteamSDK;
using Torch.API;
using Torch.API.Managers;
using Torch.Commands;
using Torch.ViewModels;
using VRage.Game;
using VRage.Game.ModAPI;
@@ -33,39 +36,44 @@ namespace Torch.Managers
/// <summary>
/// Provides a proxy to the game's multiplayer-related functions.
/// </summary>
public class MultiplayerManager : IMultiplayer
public class MultiplayerManager : Manager, IMultiplayerManager
{
public event Action<ulong> PlayerJoined;
public event Action<ulong, ConnectionState> PlayerLeft;
public event Action<IPlayer> PlayerJoined;
public event Action<IPlayer> PlayerLeft;
public event MessageReceivedDel MessageReceived;
public List<IChatMessage> ChatHistory { get; } = new List<IChatMessage>();
public Dictionary<ulong, IMyPlayer> Players { get; } = new Dictionary<ulong, IMyPlayer>();
public MTObservableCollection<IChatMessage> ChatHistory { get; } = new MTObservableCollection<IChatMessage>();
public ObservableDictionary<ulong, PlayerViewModel> Players { get; } = new ObservableDictionary<ulong, PlayerViewModel>();
public IMyPlayer LocalPlayer => MySession.Static.LocalHumanPlayer;
private readonly ITorchBase _torch;
private static Logger _log = LogManager.GetLogger(nameof(MultiplayerManager));
private static Logger _chatLog = LogManager.GetLogger("Chat");
private static readonly Logger _log = LogManager.GetLogger(nameof(MultiplayerManager));
private static readonly Logger _chatLog = LogManager.GetLogger("Chat");
private Dictionary<MyPlayer.PlayerId, MyPlayer> _onlinePlayers;
internal MultiplayerManager(ITorchBase torch)
internal MultiplayerManager(ITorchBase torch) : base(torch)
{
_torch = torch;
_torch.SessionLoaded += OnSessionLoaded;
ChatManager.Instance.MessageRecieved += Instance_MessageRecieved;
}
/// <inheritdoc />
public override void Init()
{
Torch.SessionLoaded += OnSessionLoaded;
Torch.GetManager<ChatManager>().MessageRecieved += Instance_MessageRecieved;
}
private void Instance_MessageRecieved(ChatMsg msg, ref bool sendToOthers)
{
var message = ChatMessage.FromChatMsg(msg);
ChatHistory.Add(message);
_chatLog.Info($"{message.Name}: {message.Message}");
MessageReceived?.Invoke(message, ref sendToOthers);
}
public void KickPlayer(ulong steamId) => _torch.Invoke(() => MyMultiplayer.Static.KickClient(steamId));
public void KickPlayer(ulong steamId) => Torch.Invoke(() => MyMultiplayer.Static.KickClient(steamId));
public void BanPlayer(ulong steamId, bool banned = true)
{
_torch.Invoke(() =>
Torch.Invoke(() =>
{
MyMultiplayer.Static.BanClient(steamId, banned);
if (_gameOwnerIds.ContainsKey(steamId))
@@ -94,9 +102,18 @@ namespace Torch.Managers
/// </summary>
public void SendMessage(string message, string author = "Server", long playerId = 0, string font = MyFontEnum.Red)
{
var msg = new ScriptedChatMsg {Author = author, Font = font, Target = playerId, Text = message};
MyMultiplayerBase.SendScriptedChatMessage(ref msg);
ChatHistory.Add(new ChatMessage(DateTime.Now, 0, author, message));
ChatHistory.Add(new ChatMessage(DateTime.Now, 0, "Server", message));
var commands = Torch.GetManager<CommandManager>();
if (commands.IsCommand(message))
{
var response = commands.HandleCommandFromServer(message);
ChatHistory.Add(new ChatMessage(DateTime.Now, 0, "Server", response));
}
else
{
var msg = new ScriptedChatMsg { Author = author, Font = font, Target = playerId, Text = message };
MyMultiplayerBase.SendScriptedChatMessage(ref msg);
}
}
private void OnSessionLoaded()
@@ -122,7 +139,9 @@ namespace Torch.Managers
private void OnClientLeft(ulong steamId, ChatMemberStateChangeEnum stateChange)
{
_log.Info($"{GetSteamUsername(steamId)} disconnected ({(ConnectionState)stateChange}).");
PlayerLeft?.Invoke(steamId, (ConnectionState)stateChange);
Players.TryGetValue(steamId, out PlayerViewModel vm);
PlayerLeft?.Invoke(vm ?? new PlayerViewModel(steamId));
Players.Remove(steamId);
}
//TODO: Split the following into a new file?
@@ -130,7 +149,7 @@ namespace Torch.Managers
//This lets us have a server set to private (admins only) or friends (friends of all listed admins)
private List<ulong> _members;
private HashSet<ulong> _waitingForGroup;
private HashSet<ulong> _waitingForFriends;
//private HashSet<ulong> _waitingForFriends;
private Dictionary<ulong, ulong> _gameOwnerIds = new Dictionary<ulong, ulong>();
//private IMultiplayer _multiplayerImplementation;
@@ -272,7 +291,9 @@ namespace Torch.Managers
private void UserAccepted(ulong steamId)
{
typeof(MyDedicatedServerBase).GetMethod("UserAccepted", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(MyMultiplayer.Static, new object[] {steamId});
PlayerJoined?.Invoke(steamId);
var vm = new PlayerViewModel(steamId);
Players.Add(steamId, vm);
PlayerJoined?.Invoke(vm);
}
private void UserRejected(ulong steamId, JoinResult reason)

View File

@@ -7,25 +7,31 @@ using System.Threading.Tasks;
using NLog;
using Sandbox.Engine.Multiplayer;
using Sandbox.Game.Multiplayer;
using Torch.API;
using Torch.API.Managers;
using VRage;
using VRage.Library.Collections;
using VRage.Network;
namespace Torch.Managers
{
public class NetworkManager
public class NetworkManager : Manager, INetworkManager
{
private static Logger _log = LogManager.GetLogger(nameof(NetworkManager));
public static NetworkManager Instance { get; } = new NetworkManager();
private const string MyTransportLayerField = "TransportLayer";
private const string TypeTableField = "m_typeTable";
private const string TransportHandlersField = "m_handlers";
private MyTypeTable m_typeTable = new MyTypeTable();
private HashSet<NetworkHandlerBase> _networkHandlers = new HashSet<NetworkHandlerBase>();
private HashSet<INetworkHandler> _networkHandlers = new HashSet<INetworkHandler>();
private bool _init;
private bool ReflectionUnitTest(bool suppress = false)
public NetworkManager(ITorchBase torchInstance) : base(torchInstance)
{
}
private static bool ReflectionUnitTest(bool suppress = false)
{
try
{
@@ -57,7 +63,7 @@ namespace Torch.Managers
/// <summary>
/// Loads the network intercept system
/// </summary>
public void Init()
public override void Init()
{
if (_init)
return;
@@ -196,10 +202,10 @@ namespace Torch.Managers
}
}
private void RegisterNetworkHandler(NetworkHandlerBase handler)
public void RegisterNetworkHandler(INetworkHandler handler)
{
var handlerType = handler.GetType().FullName;
var toRemove = new List<NetworkHandlerBase>();
var toRemove = new List<INetworkHandler>();
foreach (var item in _networkHandlers)
{
if (item.GetType().FullName == handlerType)
@@ -216,7 +222,7 @@ namespace Torch.Managers
_networkHandlers.Add(handler);
}
public void RegisterNetworkHandlers(params NetworkHandlerBase[] handlers)
public void RegisterNetworkHandlers(params INetworkHandler[] handlers)
{
foreach (var handler in handlers)
RegisterNetworkHandler(handler);

View File

@@ -13,6 +13,7 @@ using NLog;
using Sandbox;
using Sandbox.ModAPI;
using Torch.API;
using Torch.API.Managers;
using Torch.API.Plugins;
using Torch.Commands;
using Torch.Managers;

View File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using SteamSDK;
namespace Torch.Managers
{
/// <summary>
/// Handles updating of the DS and Torch plugins.
/// </summary>
public class UpdateManager
{
private Timer _updatePollTimer;
public UpdateManager()
{
_updatePollTimer = new Timer(CheckForUpdates, this, TimeSpan.Zero, TimeSpan.FromMinutes(5));
}
private void CheckForUpdates(object state)
{
}
}
}

View File

@@ -9,12 +9,11 @@ using Newtonsoft.Json;
namespace Torch
{
/// <summary>
/// Class that manages saving <see cref="T"/> to disk using JSON serialization.
/// Simple class that manages saving <see cref="T"/> to disk using JSON serialization.
/// </summary>
/// <typeparam name="T">Data class</typeparam>
public class Persistent<T> : IDisposable where T : new()
{
[JsonIgnore]
public string Path { get; set; }
public T Data { get; private set; }
@@ -64,7 +63,14 @@ namespace Torch
public void Dispose()
{
Save();
try
{
Save();
}
catch
{
// ignored
}
}
}

View File

@@ -35,6 +35,7 @@
<Reference Include="HavokWrapper, Version=1.0.6278.22649, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\HavokWrapper.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
@@ -51,24 +52,31 @@
<Reference Include="PresentationFramework" />
<Reference Include="Sandbox.Common">
<HintPath>..\GameBinaries\Sandbox.Common.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Sandbox.Game">
<HintPath>..\GameBinaries\Sandbox.Game.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Sandbox.Graphics">
<HintPath>..\GameBinaries\Sandbox.Graphics.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="SpaceEngineers.Game">
<HintPath>..\GameBinaries\SpaceEngineers.Game.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="SpaceEngineers.ObjectBuilders">
<HintPath>..\GameBinaries\SpaceEngineers.ObjectBuilders.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="SpaceEngineers.ObjectBuilders.XmlSerializers">
<HintPath>..\GameBinaries\SpaceEngineers.ObjectBuilders.XmlSerializers.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="SteamSDK">
<HintPath>..\GameBinaries\SteamSDK.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
@@ -81,42 +89,55 @@
<Reference Include="System.Xml" />
<Reference Include="VRage">
<HintPath>..\GameBinaries\VRage.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Audio">
<HintPath>..\GameBinaries\VRage.Audio.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Dedicated">
<HintPath>..\GameBinaries\VRage.Dedicated.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Game">
<HintPath>..\GameBinaries\VRage.Game.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Game.XmlSerializers">
<HintPath>..\GameBinaries\VRage.Game.XmlSerializers.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Input">
<HintPath>..\GameBinaries\VRage.Input.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Library">
<HintPath>..\GameBinaries\VRage.Library.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Math">
<HintPath>..\GameBinaries\VRage.Math.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Native">
<HintPath>..\GameBinaries\VRage.Native.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.OpenVRWrapper">
<HintPath>..\GameBinaries\VRage.OpenVRWrapper.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Render">
<HintPath>..\GameBinaries\VRage.Render.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Render11">
<HintPath>..\GameBinaries\VRage.Render11.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Scripting">
<HintPath>..\GameBinaries\VRage.Scripting.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="WindowsBase" />
</ItemGroup>
@@ -137,11 +158,12 @@
<Compile Include="Commands\TorchCommands.cs" />
<Compile Include="Managers\ChatManager.cs" />
<Compile Include="Managers\EntityManager.cs" />
<Compile Include="Managers\Manager.cs" />
<Compile Include="Managers\NetworkManager\NetworkHandlerBase.cs" />
<Compile Include="Managers\NetworkManager\NetworkManager.cs" />
<Compile Include="Managers\MultiplayerManager.cs" />
<Compile Include="Managers\UpdateManager.cs" />
<Compile Include="Persistent.cs" />
<Compile Include="TorchConfig.cs" />
<Compile Include="Updater\PluginManifest.cs" />
<Compile Include="Reflection.cs" />
<Compile Include="Managers\ScriptingManager.cs" />
@@ -154,6 +176,7 @@
<Compile Include="Extensions\MyPlayerCollectionExtensions.cs" />
<Compile Include="SteamHelper.cs" />
<Compile Include="Extensions\StringExtensions.cs" />
<Compile Include="ViewModels\PlayerViewModel.cs" />
<Compile Include="ViewModels\ViewModel.cs" />
<Compile Include="Managers\PluginManager.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />

View File

@@ -17,8 +17,10 @@ using Sandbox.Game.World;
using Sandbox.ModAPI;
using SpaceEngineers.Game;
using Torch.API;
using Torch.API.Managers;
using Torch.Commands;
using Torch.Managers;
using VRage.Collections;
using VRage.FileSystem;
using VRage.Game.ObjectBuilder;
using VRage.ObjectBuilders;
@@ -41,14 +43,15 @@ namespace Torch
public Version GameVersion { get; private set; }
public string[] RunArgs { get; set; }
public IPluginManager Plugins { get; protected set; }
public IMultiplayer Multiplayer { get; protected set; }
public IMultiplayerManager Multiplayer { get; protected set; }
public EntityManager Entities { get; protected set; }
public NetworkManager Network { get; protected set; }
public INetworkManager Network { get; protected set; }
public CommandManager Commands { get; protected set; }
public event Action SessionLoading;
public event Action SessionLoaded;
public event Action SessionUnloading;
public event Action SessionUnloaded;
private HashSet<IManager> _managers;
private bool _init;
@@ -61,11 +64,40 @@ namespace Torch
TorchVersion = Assembly.GetExecutingAssembly().GetName().Version;
RunArgs = new string[0];
Plugins = new PluginManager(this);
Multiplayer = new MultiplayerManager(this);
Entities = new EntityManager(this);
Network = NetworkManager.Instance;
Network = new NetworkManager(this);
Commands = new CommandManager(this);
_managers = new HashSet<IManager>
{
Plugins,
Multiplayer,
Entities,
Network,
Commands
};
}
public HashSetReader<IManager> GetManagers()
{
return new HashSetReader<IManager>(_managers);
}
public T GetManager<T>() where T : class, IManager
{
return _managers.FirstOrDefault(m => m is T) as T;
}
public bool AddManager<T>(T manager) where T : class, IManager
{
if (_managers.Any(x => x is T))
return false;
_managers.Add(manager);
return true;
}
public bool IsOnGameThread()
@@ -91,9 +123,9 @@ namespace Torch
if (!e.WaitOne(60000))
{
Log.Error("Save failed!");
Multiplayer.SendMessage("Save timed out!", author: "Error");
Multiplayer.SendMessage("Save timed out!", "Error");
}
});
}).ConfigureAwait(false);
}
}
else
@@ -233,8 +265,8 @@ namespace Torch
/// <inheritdoc />
public virtual void Init(object gameInstance)
{
Network.Init();
ChatManager.Instance.Init();
foreach (var manager in _managers)
manager.Init();
}
/// <inheritdoc />

View File

@@ -37,7 +37,7 @@ namespace Torch.Updater
}
var gitClient = new GitHubClient(new ProductHeaderValue("Torch"));
var releases = await gitClient.Repository.Release.GetAll(split[0], split[1]);
var releases = await gitClient.Repository.Release.GetAll(split[0], split[1]).ConfigureAwait(false);
if (releases.Count == 0)
{
@@ -62,14 +62,14 @@ namespace Torch.Updater
if (force || latestVersion > currentVersion)
{
var webClient = new WebClient();
var assets = await gitClient.Repository.Release.GetAllAssets(split[0], split[1], releases[0].Id);
var assets = await gitClient.Repository.Release.GetAllAssets(split[0], split[1], releases[0].Id).ConfigureAwait(false);
foreach (var asset in assets)
{
if (asset.Name.EndsWith(".zip"))
{
Log.Debug(asset.BrowserDownloadUrl);
var localPath = Path.Combine(Path.GetTempPath(), asset.Name);
await webClient.DownloadFileTaskAsync(new Uri(asset.BrowserDownloadUrl), localPath);
await webClient.DownloadFileTaskAsync(new Uri(asset.BrowserDownloadUrl), localPath).ConfigureAwait(false);
UnzipPlugin(localPath);
Log.Info($"Downloaded update for {manifest.Repository}");
return;

View File

@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SteamSDK;
using Torch.API;
namespace Torch.ViewModels
{
public class PlayerViewModel : ViewModel, IPlayer
{
public ulong SteamId { get; }
public string Name { get; }
private ConnectionState _state;
public ConnectionState State { get => _state; set { _state = value; OnPropertyChanged(); } }
public PlayerViewModel(ulong steamId, string name = null)
{
SteamId = steamId;
Name = name ?? SteamAPI.Instance?.Friends?.GetPersonaName(steamId) ?? "???";
}
}
}