Fix DS loading, add NLog for logging

This commit is contained in:
John Gross
2017-01-03 23:09:09 -08:00
parent a3e29fff4e
commit 15af769d90
25 changed files with 144 additions and 149 deletions

View File

@@ -15,19 +15,19 @@ namespace TestPlugin
public override void Init(ITorchBase torch)
{
base.Init(torch);
Torch.Log.Write($"Plugin init {Name}");
//Torch.Log.Write($"Plugin init {Name}");
}
/// <inheritdoc />
public override void Update()
{
Torch.Log.Write($"Plugin update {Name}");
//Torch.Log.Write($"Plugin update {Name}");
}
/// <inheritdoc />
public override void Unload()
{
Torch.Log.Write($"Plugin unload {Name}");
//Torch.Log.Write($"Plugin unload {Name}");
}
}
}

View File

@@ -1,14 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Torch.API
{
public interface ILogger
{
void Write(string message);
void WriteException(Exception e);
}
}

View File

@@ -9,5 +9,6 @@ namespace Torch.API
{
void UpdatePlugins();
void LoadPlugins();
void UnloadPlugins();
}
}

View File

@@ -11,7 +11,6 @@ namespace Torch.API
event Action SessionLoaded;
IMultiplayer Multiplayer { get; }
IPluginManager Plugins { get; }
ILogger Log { get; set; }
void Invoke(Action action);
void InvokeBlocking(Action action);
Task InvokeAsync(Action action);

View File

@@ -13,8 +13,20 @@ namespace Torch.API
Version Version { get; }
string Name { get; }
/// <summary>
/// Called when the game is initialized.
/// </summary>
/// <param name="torchBase"></param>
void Init(ITorchBase torchBase);
/// <summary>
/// Called after each game tick. Not thread safe, use invocation methods in <see cref="ITorchBase"/>.
/// </summary>
void Update();
/// <summary>
/// Called when the game exits.
/// </summary>
void Unload();
}
}

View File

@@ -32,10 +32,18 @@
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="NLog">
<HintPath>..\packages\NLog.4.4.1\lib\net45\NLog.dll</HintPath>
</Reference>
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Core" />
<Reference Include="System.IO.Compression" />
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.ServiceModel" />
<Reference Include="System.Transactions" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
@@ -53,7 +61,6 @@
<ItemGroup>
<Compile Include="ConnectionState.cs" />
<Compile Include="IChatItem.cs" />
<Compile Include="ILogger.cs" />
<Compile Include="IMultiplayer.cs" />
<Compile Include="IPlayer.cs" />
<Compile Include="IPluginManager.cs" />
@@ -63,6 +70,9 @@
<Compile Include="PluginAttribute.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="NLog" version="4.4.1" targetFramework="net461" />
</packages>

View File

@@ -37,6 +37,10 @@
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<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>
<Private>True</Private>
</Reference>
<Reference Include="Sandbox.Game">
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\Sandbox.Game.dll</HintPath>
</Reference>
@@ -108,6 +112,7 @@
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>

View File

@@ -85,7 +85,7 @@ namespace Torch.Client
{
using (var spaceEngineersGame = new SpaceEngineersGame(_services, RunArgs))
{
Log.Write("Starting client...");
Log.Info("Starting client");
spaceEngineersGame.OnGameLoaded += SpaceEngineersGame_OnGameLoaded;
spaceEngineersGame.Run();
}
@@ -93,8 +93,6 @@ namespace Torch.Client
private void SpaceEngineersGame_OnGameLoaded(object sender, EventArgs e)
{
Log.Write("Loading plugins");
Plugins.LoadAllPlugins();
}
public override void Stop()

View File

@@ -28,10 +28,9 @@ namespace Torch.Client
VisibleRowsCount = 10,
};
foreach (var plugin in TorchBase.Instance.Plugins.Plugins)
foreach (var plugin in TorchBase.Instance.Plugins)
{
var name = TorchBase.Instance.Plugins.GetPluginName(plugin.GetType());
pluginList.Items.Add(new MyGuiControlListbox.Item(new StringBuilder(name)));
pluginList.Items.Add(new MyGuiControlListbox.Item(new StringBuilder(plugin.Name)));
}
Controls.Add(pluginList);
}

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="NLog" version="4.4.1" targetFramework="net461" />
</packages>

View File

@@ -26,13 +26,12 @@ namespace Torch.Server
{
ServiceBase.Run(service);
}
return;
}
else
{
_server = new TorchServer();
_server.Init();
_server.Start();
}
}
}
}

View File

@@ -47,6 +47,10 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\DedicatedServer64\HavokWrapper.dll</HintPath>
</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>
<Private>True</Private>
</Reference>
<Reference Include="Sandbox.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\DedicatedServer64\Sandbox.Common.dll</HintPath>

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
@@ -11,6 +12,7 @@ using Torch;
using Sandbox;
using Sandbox.Engine.Multiplayer;
using Sandbox.Game;
using Sandbox.Game.Gui;
using Sandbox.Game.World;
using SpaceEngineers.Game;
using Torch.API;
@@ -66,7 +68,6 @@ namespace Torch.Server
private void OnSessionReady()
{
Plugins.LoadPlugins();
InvokeSessionLoaded();
}
@@ -79,12 +80,12 @@ namespace Torch.Server
throw new InvalidOperationException("Server is already running.");
IsRunning = true;
Log.Write("Starting server.");
Log.Info("Starting server.");
if (MySandboxGame.Log.LogEnabled)
MySandboxGame.Log.Close();
MySandboxGame.IsDedicated = true;
Environment.SetEnvironmentVariable("SteamAppId", MyPerServerSettings.AppId.ToString());
DedicatedServer.Run<MyObjectBuilder_SessionSettings>(RunArgs);
Reflection.InvokeStaticMethod(typeof(DedicatedServer), "RunMain", "Torch", null, true);
}
/// <summary>
@@ -94,13 +95,13 @@ namespace Torch.Server
{
if (Thread.CurrentThread.ManagedThreadId != GameThread?.ManagedThreadId)
{
Log.Write("Requesting server stop.");
Log.Info("Requesting server stop.");
MySandboxGame.Static.Invoke(Stop);
_stopHandle.WaitOne();
return;
}
Log.Write("Stopping server.");
Log.Info("Stopping server.");
MySession.Static.Save();
MySession.Static.Unload();
MySandboxGame.Static.Exit();
@@ -112,7 +113,7 @@ namespace Torch.Server
VRage.Input.MyInput.UnloadData();
CleanupProfilers();
Log.Write("Server stopped.");
Log.Info("Server stopped.");
_stopHandle.Set();
IsRunning = false;
}

View File

@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Extended.Wpf.Toolkit" version="2.9" targetFramework="net461" />
<package id="NLog" version="4.4.1" targetFramework="net461" />
</packages>

View File

@@ -82,7 +82,7 @@ namespace Torch.Commands
var context = new CommandContext
{
Args = arg,
//Args = arg,
SteamId = steamId
};

View File

@@ -1,64 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using Sandbox;
using Torch.API;
using VRage.Utils;
namespace Torch
{
public class Logger : ILogger
{
public string Prefix = "[TORCH]";
private StringBuilder _sb = new StringBuilder();
private string _path;
public Logger(string path)
{
_path = path;
if (File.Exists(_path))
File.Delete(_path);
}
public void Write(string message)
{
var msg = $"{GetInfo()}: {message}";
Console.WriteLine(msg);
_sb.AppendLine(msg);
}
public void WriteExceptionAndThrow(Exception e)
{
WriteException(e);
throw e;
}
public void WriteException(Exception e)
{
_sb.AppendLine($"{GetInfo()}: {e.Message}");
foreach (var line in e.StackTrace.Split('\n'))
_sb.AppendLine($"\t{line}");
}
private string GetInfo()
{
return $"{DateTime.Now.ToShortDateString()} {DateTime.Now.ToShortTimeString()} {Prefix}";
}
public void Flush()
{
File.AppendAllText(_path, _sb.ToString());
_sb.Clear();
}
~Logger()
{
Flush();
}
}
}

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using NLog;
using Sandbox.Engine.Multiplayer;
using Sandbox.Game.Multiplayer;
using VRage;
@@ -19,6 +20,7 @@ namespace Torch.Managers
InitNetworkIntercept();
}
private static Logger _log = LogManager.GetCurrentClassLogger();
private static NetworkManager _instance;
public static NetworkManager Instance => _instance ?? (_instance = new NetworkManager());
@@ -51,9 +53,8 @@ namespace Torch.Managers
}
catch (TypeLoadException ex)
{
//ApplicationLog.BaseLog.Error(ex);
TorchBase.Instance.Log.WriteException(ex);
if ( suppress )
_log.Error(ex);
if (suppress)
return false;
throw;
}
@@ -99,7 +100,7 @@ namespace Torch.Managers
}
catch (Exception ex)
{
TorchBase.Instance.Log.WriteException(ex);
_log.Error(ex);
//ApplicationLog.Error(ex, "~Error processing event!");
//crash after logging, bad things could happen if we continue on with bad data
throw;
@@ -159,7 +160,7 @@ namespace Torch.Managers
catch (Exception ex)
{
//ApplicationLog.Error(ex.ToString());
TorchBase.Instance.Log.WriteException(ex);
_log.Error(ex);
}
});
@@ -174,7 +175,7 @@ namespace Torch.Managers
}
catch (Exception ex)
{
TorchBase.Instance.Log.WriteException(ex);
_log.Error(ex);
//ApplicationLog.Error(ex, "Error when returning control to game server!");
//crash after logging, bad things could happen if we continue on with bad data
throw;

View File

@@ -12,6 +12,7 @@ using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
using System.Windows.Threading;
using NLog;
using Torch;
using Sandbox;
using Sandbox.Engine.Multiplayer;
@@ -43,6 +44,7 @@ namespace Torch
public Player LocalPlayer { get; private set; }
private readonly ITorchBase _torch;
private static Logger _log = LogManager.GetCurrentClassLogger();
internal MultiplayerManager(ITorchBase torch)
{
@@ -118,7 +120,7 @@ namespace Torch
player.SetConnectionState(ConnectionState.Connected);
}
_torch.Log.Write($"{player.Name} connected.");
_log.Info($"{player.Name} connected.");
PlayerJoined?.Invoke(player);
}
@@ -133,7 +135,7 @@ namespace Torch
return;
var player = Players[steamId];
_torch.Log.Write($"{player.Name} disconnected ({(ConnectionState)stateChange}).");
_log.Info($"{player.Name} disconnected ({(ConnectionState)stateChange}).");
player.SetConnectionState((ConnectionState)stateChange);
PlayerLeft?.Invoke(player);
}
@@ -179,16 +181,16 @@ namespace Torch
//Largely copied from SE
private void ValidateAuthTicketResponse(ulong steamID, AuthSessionResponseEnum response, ulong ownerSteamID)
{
_torch.Log.Write($"Server ValidateAuthTicketResponse ({response}), owner: {ownerSteamID}");
_log.Info($"Server ValidateAuthTicketResponse ({response}), owner: {ownerSteamID}");
if (steamID != ownerSteamID)
{
_torch.Log.Write($"User {steamID} is using a game owned by {ownerSteamID}. Tracking...");
_log.Info($"User {steamID} is using a game owned by {ownerSteamID}. Tracking...");
_gameOwnerIds[steamID] = ownerSteamID;
if (MySandboxGame.ConfigDedicated.Banned.Contains(ownerSteamID))
{
_torch.Log.Write($"Game owner {ownerSteamID} is banned. Banning and rejecting client {steamID}...");
_log.Info($"Game owner {ownerSteamID} is banned. Banning and rejecting client {steamID}...");
UserRejected(steamID, JoinResult.BannedByAdmins);
BanPlayer(steamID, true);
}

View File

@@ -9,6 +9,7 @@ using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using NLog;
using Sandbox;
using Sandbox.ModAPI;
using Torch.API;
@@ -18,36 +19,19 @@ using VRage.Library.Collections;
namespace Torch
{
internal class TorchPluginUpdater : IPlugin
{
private readonly IPluginManager _manager;
public TorchPluginUpdater(IPluginManager manager)
{
_manager = manager;
}
public void Init(object obj) { }
public void Update()
{
_manager.UpdatePlugins();
}
public void Dispose() { }
}
public class PluginManager : IPluginManager
{
private readonly ITorchBase _torch;
private static Logger _log = LogManager.GetCurrentClassLogger();
public const string PluginDir = "Plugins";
private readonly List<ITorchPlugin> _plugins = new List<ITorchPlugin>();
private readonly TorchPluginUpdater _updater;
private readonly PluginUpdater _updater;
public PluginManager(ITorchBase torch)
{
_torch = torch;
_updater = new TorchPluginUpdater(this);
_updater = new PluginUpdater(this);
if (!Directory.Exists(PluginDir))
Directory.CreateDirectory(PluginDir);
@@ -57,9 +41,10 @@ namespace Torch
private void InitUpdater()
{
var pluginList = typeof(MyPlugins).GetField("m_plugins", BindingFlags.Static | BindingFlags.NonPublic)?.GetValue(null) as List<IPlugin>;
var fieldName = "m_plugins";
var pluginList = typeof(MyPlugins).GetField(fieldName, BindingFlags.Static | BindingFlags.NonPublic)?.GetValue(null) as List<IPlugin>;
if (pluginList == null)
throw new TypeLoadException($"m_plugins field not found in {nameof(MyPlugins)}");
throw new TypeLoadException($"{fieldName} field not found in {nameof(MyPlugins)}");
pluginList.Add(_updater);
}
@@ -78,7 +63,7 @@ namespace Torch
}
/// <summary>
/// Load all plugins in the <see cref="PluginDir"/> folder.
/// Load and create instances of all plugins in the <see cref="PluginDir"/> folder.
/// </summary>
public void LoadPlugins()
{
@@ -92,7 +77,11 @@ namespace Torch
foreach (var type in asm.GetExportedTypes())
{
if (type.GetInterfaces().Contains(typeof(ITorchPlugin)))
_plugins.Add((ITorchPlugin)Activator.CreateInstance(type));
{
var plugin = (ITorchPlugin)Activator.CreateInstance(type);
_log.Info($"Loading plugin {plugin.Name} ({plugin.Version})");
_plugins.Add(plugin);
}
}
}
}
@@ -119,5 +108,32 @@ namespace Torch
[DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool DeleteFile(string name);
/// <summary>
/// Tiny "plugin" to call <see cref="PluginManager"/>'s update method after each game tick.
/// </summary>
private class PluginUpdater : IPlugin
{
private readonly IPluginManager _manager;
public PluginUpdater(IPluginManager manager)
{
_manager = manager;
}
public void Init(object obj)
{
_manager.LoadPlugins();
}
public void Update()
{
_manager.UpdatePlugins();
}
public void Dispose()
{
_manager.UnloadPlugins();
}
}
}
}

View File

@@ -110,5 +110,14 @@ namespace Torch
return false;
}
}
public static object InvokeStatic(Type type, string methodName, params object[] args)
{
var method = type.GetMethod(methodName, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
if (method == null)
throw new TypeLoadException($"Method {methodName} not found in static class {type.FullName}");
return method.Invoke(null, args);
}
}
}

View File

@@ -4,6 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using NLog;
using Sandbox;
using Sandbox.Engine.Networking;
using Sandbox.Engine.Platform;
@@ -16,12 +17,10 @@ namespace Torch
public static class SteamHelper
{
private static Thread _callbackThread;
private static ILogger _log;
private static Logger _log = LogManager.GetLogger("Torch");
public static void Init(ILogger log)
public static void Init()
{
_log = log;
_callbackThread = new Thread(() =>
{
while (true)
@@ -56,7 +55,7 @@ namespace Torch
}
else
{
_log.Write($"Failed to get item info for {itemId}");
_log.Warn($"Failed to get item info for {itemId}");
}
mre.Set();
@@ -79,7 +78,7 @@ namespace Torch
if (!b && result.Details.Result == Result.OK)
details = result.Details;
else
_log.Write($"Failed to get item details for {itemId}");
_log.Warn($"Failed to get item details for {itemId}");
re.Set();
});

View File

@@ -32,6 +32,10 @@
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<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>
<Private>True</Private>
</Reference>
<Reference Include="Sandbox.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\Sandbox.Common.dll</HintPath>
@@ -128,7 +132,6 @@
<Compile Include="Commands\CommandContext.cs" />
<Compile Include="Commands\CommandSystem.cs" />
<Compile Include="Commands\CommandTree.cs" />
<Compile Include="Logger.cs" />
<Compile Include="Managers\ChatManager.cs" />
<Compile Include="Managers\NetworkManager\NetworkHandlerBase.cs" />
<Compile Include="Managers\NetworkManager\NetworkManager.cs" />
@@ -156,7 +159,9 @@
<Name>Torch.API</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup />
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

View File

@@ -6,6 +6,7 @@ using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using NLog;
using Sandbox;
using Torch.API;
using VRage.Scripting;
@@ -20,10 +21,10 @@ namespace Torch
/// </summary>
[Obsolete]
public static ITorchBase Instance { get; private set; }
protected static Logger Log = LogManager.GetLogger("Torch");
public string[] RunArgs { get; set; }
public IPluginManager Plugins { get; protected set; }
public IMultiplayer Multiplayer { get; protected set; }
public ILogger Log { get; set; }
public event Action SessionLoaded;
private bool _init;
@@ -40,7 +41,6 @@ namespace Torch
Instance = this;
Log = new Logger(Path.Combine(Directory.GetCurrentDirectory(), "TorchLog.log"));
RunArgs = new string[0];
Plugins = new PluginManager(this);
Multiplayer = new MultiplayerManager(this);

4
Torch/packages.config Normal file
View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="NLog" version="4.4.1" targetFramework="net461" />
</packages>