updated NLog to v5
fixed most of issues with world creating/loading fixed log window lags fixed some compiler warnings fixed empty log files creating fixed logging performance added better logging of load process
This commit is contained in:
11
NLog.config
11
NLog.config
@@ -4,14 +4,17 @@
|
||||
<variable name="logStamp" value="${time} ${pad:padding=-8:inner=[${level:uppercase=true}]}" />
|
||||
<variable name="logContent" value="${message:withException=true}"/>
|
||||
|
||||
<targets async="true">
|
||||
<targets>
|
||||
<default-wrapper xsi:type="AsyncWrapper" overflowAction="Block" optimizeBufferReuse="true" />
|
||||
<target xsi:type="Null" name="null" formatMessage="false" />
|
||||
<target xsi:type="File" name="keen" layout="${var:logStamp} ${logger}: ${var:logContent}" fileName="Logs\Keen-${shortdate}.log" />
|
||||
<target xsi:type="File" name="main" layout="${var:logStamp} ${logger}: ${var:logContent}" fileName="Logs\Torch-${shortdate}.log" />
|
||||
<target xsi:type="File" keepFileOpen="true" concurrentWrites="false" name="keen" layout="${var:logStamp} ${logger}: ${var:logContent}"
|
||||
fileName="Logs\Keen-${shortdate}.log" />
|
||||
<target xsi:type="File" keepFileOpen="true" concurrentWrites="false" name="main" layout="${var:logStamp} ${logger}: ${var:logContent}"
|
||||
fileName="Logs\Torch-${shortdate}.log" />
|
||||
<target xsi:type="File" name="chat" layout="${longdate} ${message}" fileName="Logs\Chat.log" />
|
||||
<target xsi:type="ColoredConsole" name="console" layout="${var:logStamp} ${logger:shortName=true}: ${var:logContent}" />
|
||||
<target xsi:type="File" name="patch" layout="${var:logContent}" fileName="Logs\patch.log"/>
|
||||
<target xsi:type="FlowDocument" name="wpf" layout="${var:logStamp} ${logger:shortName=true}: ${var:logContent}" />
|
||||
<target xsi:type="LogViewerTarget" name="wpf" layout="[${level:uppercase=true}] ${logger:shortName=true}: ${var:logContent}" />
|
||||
</targets>
|
||||
|
||||
<rules>
|
||||
|
@@ -29,7 +29,7 @@ namespace Torch
|
||||
int WindowHeight { get; set; }
|
||||
int FontSize { get; set; }
|
||||
UGCServiceType UgcServiceType { get; set; }
|
||||
|
||||
bool EntityManagerEnabled { get; set; }
|
||||
void Save(string path = null);
|
||||
}
|
||||
}
|
@@ -23,6 +23,11 @@ namespace Torch.API.Session
|
||||
/// </summary>
|
||||
MySession KeenSession { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Currently running world
|
||||
/// </summary>
|
||||
IWorld World { get; }
|
||||
|
||||
/// <inheritdoc cref="IDependencyManager"/>
|
||||
IDependencyManager Managers { get; }
|
||||
|
||||
|
@@ -17,7 +17,7 @@
|
||||
</PropertyGroup>
|
||||
<!-- <Import Project="$(SolutionDir)\TransformOnBuild.targets" /> -->
|
||||
<ItemGroup>
|
||||
<PackageReference Include="NLog" Version="4.7.13" />
|
||||
<PackageReference Include="NLog" Version="5.0.0-rc2" />
|
||||
<PackageReference Include="SemanticVersioning" Version="2.0.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@@ -18,7 +18,7 @@
|
||||
<!-- <Import Project="$(SolutionDir)\TransformOnBuild.targets" /> -->
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
|
||||
<PackageReference Include="NLog" Version="4.7.13" />
|
||||
<PackageReference Include="NLog" Version="5.0.0-rc2" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@@ -1,54 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Media;
|
||||
using NLog;
|
||||
using NLog.Targets;
|
||||
|
||||
namespace Torch.Server
|
||||
{
|
||||
/// <summary>
|
||||
/// NLog target that writes to a <see cref="FlowDocument"/>.
|
||||
/// </summary>
|
||||
[Target("flowDocument")]
|
||||
public sealed class FlowDocumentTarget : TargetWithLayout
|
||||
{
|
||||
private FlowDocument _document = new FlowDocument { Background = new SolidColorBrush(Colors.Black) };
|
||||
private readonly Paragraph _paragraph = new Paragraph();
|
||||
private readonly int _maxLines = 500;
|
||||
|
||||
public FlowDocument Document => _document;
|
||||
|
||||
public FlowDocumentTarget()
|
||||
{
|
||||
_document.Blocks.Add(_paragraph);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Write(LogEventInfo logEvent)
|
||||
{
|
||||
_document.Dispatcher.BeginInvoke(() =>
|
||||
{
|
||||
var message = $"{Layout.Render(logEvent)}\n";
|
||||
_paragraph.Inlines.Add(new Run(message) {Foreground = LogLevelColors[logEvent.Level]});
|
||||
|
||||
// A massive paragraph slows the UI down
|
||||
if (_paragraph.Inlines.Count > _maxLines)
|
||||
_paragraph.Inlines.Remove(_paragraph.Inlines.FirstInline);
|
||||
});
|
||||
}
|
||||
|
||||
private static readonly Dictionary<LogLevel, SolidColorBrush> LogLevelColors = new Dictionary<LogLevel, SolidColorBrush>
|
||||
{
|
||||
[LogLevel.Trace] = new SolidColorBrush(Colors.DimGray),
|
||||
[LogLevel.Debug] = new SolidColorBrush(Colors.DarkGray),
|
||||
[LogLevel.Info] = new SolidColorBrush(Colors.White),
|
||||
[LogLevel.Warn] = new SolidColorBrush(Colors.Magenta),
|
||||
[LogLevel.Error] = new SolidColorBrush(Colors.Yellow),
|
||||
[LogLevel.Fatal] = new SolidColorBrush(Colors.Red),
|
||||
};
|
||||
}
|
||||
}
|
@@ -5,6 +5,7 @@ using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
@@ -156,6 +157,10 @@ quit";
|
||||
gameThread.Start();
|
||||
|
||||
var ui = new TorchUI(_server);
|
||||
|
||||
SynchronizationContext.SetSynchronizationContext(
|
||||
new DispatcherSynchronizationContext(Dispatcher.CurrentDispatcher));
|
||||
|
||||
ui.ShowDialog();
|
||||
}
|
||||
}
|
||||
@@ -192,8 +197,9 @@ quit";
|
||||
try
|
||||
{
|
||||
log.Info("Downloading SteamCMD.");
|
||||
using (var client = new WebClient())
|
||||
client.DownloadFile("https://steamcdn-a.akamaihd.net/client/installer/steamcmd.zip", STEAMCMD_ZIP);
|
||||
using (var client = new HttpClient())
|
||||
using (var file = File.Create(STEAMCMD_ZIP))
|
||||
client.GetStreamAsync("https://steamcdn-a.akamaihd.net/client/installer/steamcmd.zip").Result.CopyTo(file);
|
||||
|
||||
ZipFile.ExtractToDirectory(STEAMCMD_ZIP, STEAMCMD_DIR);
|
||||
File.Delete(STEAMCMD_ZIP);
|
||||
|
51
Torch.Server/LogViewerTarget.cs
Normal file
51
Torch.Server/LogViewerTarget.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Threading;
|
||||
using NLog;
|
||||
using NLog.Targets;
|
||||
using Torch.Server.ViewModels;
|
||||
using Torch.Server.Views;
|
||||
|
||||
namespace Torch.Server
|
||||
{
|
||||
/// <summary>
|
||||
/// NLog target that writes to a <see cref="LogViewerControl"/>.
|
||||
/// </summary>
|
||||
[Target("logViewer")]
|
||||
public sealed class LogViewerTarget : TargetWithLayout
|
||||
{
|
||||
public IList<LogEntry> LogEntries { get; set; }
|
||||
public SynchronizationContext TargetContext { get; set; }
|
||||
private readonly int _maxLines = 1000;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Write(LogEventInfo logEvent)
|
||||
{
|
||||
TargetContext?.Post(_sendOrPostCallback, logEvent);
|
||||
}
|
||||
|
||||
private void WriteCallback(object state)
|
||||
{
|
||||
var logEvent = (LogEventInfo) state;
|
||||
LogEntries?.Add(new(logEvent.TimeStamp, Layout.Render(logEvent), LogLevelColors[logEvent.Level]));
|
||||
}
|
||||
|
||||
private static readonly Dictionary<LogLevel, SolidColorBrush> LogLevelColors = new()
|
||||
{
|
||||
[LogLevel.Trace] = new SolidColorBrush(Colors.DimGray),
|
||||
[LogLevel.Debug] = new SolidColorBrush(Colors.DarkGray),
|
||||
[LogLevel.Info] = new SolidColorBrush(Colors.White),
|
||||
[LogLevel.Warn] = new SolidColorBrush(Colors.Magenta),
|
||||
[LogLevel.Error] = new SolidColorBrush(Colors.Yellow),
|
||||
[LogLevel.Fatal] = new SolidColorBrush(Colors.Red),
|
||||
};
|
||||
|
||||
private readonly SendOrPostCallback _sendOrPostCallback;
|
||||
|
||||
public LogViewerTarget()
|
||||
{
|
||||
_sendOrPostCallback = WriteCallback;
|
||||
}
|
||||
}
|
||||
}
|
@@ -5,6 +5,7 @@ using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Havok;
|
||||
@@ -30,7 +31,7 @@ using VRage.Plugins;
|
||||
|
||||
namespace Torch.Server.Managers
|
||||
{
|
||||
public class InstanceManager : Manager
|
||||
public class InstanceManager : Manager, IInstanceManager
|
||||
{
|
||||
private const string CONFIG_NAME = "SpaceEngineers-Dedicated.cfg";
|
||||
|
||||
@@ -45,6 +46,8 @@ namespace Torch.Server.Managers
|
||||
|
||||
}
|
||||
|
||||
public IWorld SelectedWorld => DedicatedConfig.SelectedWorld;
|
||||
|
||||
public void LoadInstance(string path, bool validate = true)
|
||||
{
|
||||
Log.Info($"Loading instance {path}");
|
||||
@@ -221,14 +224,11 @@ namespace Torch.Server.Managers
|
||||
|
||||
public void SaveConfig()
|
||||
{
|
||||
if (((TorchServer)Torch).HasRun)
|
||||
if (!((TorchServer)Torch).HasRun)
|
||||
{
|
||||
Log.Warn("Checkpoint cache is stale, not saving dedicated config.");
|
||||
return;
|
||||
}
|
||||
|
||||
DedicatedConfig.Save(Path.Combine(Torch.Config.InstancePath, CONFIG_NAME));
|
||||
Log.Info("Saved dedicated config.");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
@@ -255,7 +255,7 @@ namespace Torch.Server.Managers
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error("Failed to write sandbox config, changes will not appear on server");
|
||||
Log.Error("Failed to write sandbox config");
|
||||
Log.Error(e);
|
||||
}
|
||||
}
|
||||
@@ -276,12 +276,14 @@ namespace Torch.Server.Managers
|
||||
}
|
||||
}
|
||||
|
||||
public class WorldViewModel : ViewModel
|
||||
public class WorldViewModel : ViewModel, IWorld
|
||||
{
|
||||
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
|
||||
|
||||
public string FolderName { get; set; }
|
||||
public string WorldPath { get; }
|
||||
public MyObjectBuilder_SessionSettings KeenSessionSettings => WorldConfiguration.Settings;
|
||||
public MyObjectBuilder_Checkpoint KeenCheckpoint => Checkpoint;
|
||||
public long WorldSizeKB { get; }
|
||||
private string _checkpointPath;
|
||||
private string _worldConfigPath;
|
||||
@@ -329,13 +331,15 @@ namespace Torch.Server.Managers
|
||||
|
||||
public void LoadSandbox()
|
||||
{
|
||||
MyObjectBuilderSerializer.DeserializeXML(_checkpointPath, out MyObjectBuilder_Checkpoint checkpoint);
|
||||
if (!MyObjectBuilderSerializer.DeserializeXML(_checkpointPath, out MyObjectBuilder_Checkpoint checkpoint))
|
||||
throw new SerializationException("Error reading checkpoint, see keen log for details");
|
||||
Checkpoint = new CheckpointViewModel(checkpoint);
|
||||
|
||||
// migrate old saves
|
||||
if (File.Exists(_worldConfigPath))
|
||||
{
|
||||
MyObjectBuilderSerializer.DeserializeXML(_worldConfigPath, out MyObjectBuilder_WorldConfiguration worldConfig);
|
||||
if (!MyObjectBuilderSerializer.DeserializeXML(_worldConfigPath, out MyObjectBuilder_WorldConfiguration worldConfig))
|
||||
throw new SerializationException("Error reading settings, see keen log for details");
|
||||
WorldConfiguration = new WorldConfigurationViewModel(worldConfig);
|
||||
}
|
||||
else
|
||||
|
@@ -25,7 +25,7 @@ namespace Torch.Server
|
||||
[STAThread]
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
Target.Register<FlowDocumentTarget>("FlowDocument");
|
||||
Target.Register<LogViewerTarget>(nameof(LogViewerTarget));
|
||||
//Ensures that all the files are downloaded in the Torch directory.
|
||||
var workingDir = new FileInfo(typeof(Program).Assembly.Location).Directory!.FullName;
|
||||
var binDir = Path.Combine(workingDir, "DedicatedServer64");
|
||||
|
@@ -3,7 +3,7 @@
|
||||
"profiles": {
|
||||
"Torch.Server": {
|
||||
"commandName": "Project",
|
||||
|
||||
"commandLineArgs": "-noupdate",
|
||||
"use64Bit": true,
|
||||
"hotReloadEnabled": false
|
||||
}
|
||||
|
@@ -39,12 +39,13 @@
|
||||
</PropertyGroup>
|
||||
<!-- <Import Project="$(SolutionDir)\TransformOnBuild.targets" /> -->
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AutoCompleteTextBox" Version="1.3.0" />
|
||||
<PackageReference Include="Ben.Demystifier" Version="0.4.1" />
|
||||
<PackageReference Include="ControlzEx" Version="5.0.1" />
|
||||
<PackageReference Include="MahApps.Metro" Version="2.4.9" />
|
||||
<PackageReference Include="MdXaml" Version="1.12.0" />
|
||||
<PackageReference Include="Microsoft.Diagnostics.Runtime" Version="2.0.226801" />
|
||||
<PackageReference Include="NLog" Version="4.7.13" />
|
||||
<PackageReference Include="NLog" Version="5.0.0-rc2" />
|
||||
<PackageReference Include="PropertyChanged.Fody" Version="3.4.0" PrivateAssets="all" />
|
||||
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
||||
<PackageReference Include="System.Management" Version="6.0.0" />
|
||||
|
@@ -10,6 +10,7 @@ using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Diagnostics.Runtime;
|
||||
using NLog;
|
||||
using PropertyChanged;
|
||||
using Sandbox;
|
||||
using Sandbox.Engine.Multiplayer;
|
||||
using Sandbox.Game.Multiplayer;
|
||||
@@ -212,6 +213,7 @@ namespace Torch.Server
|
||||
Environment.Exit(0);
|
||||
}
|
||||
|
||||
[SuppressPropertyChangedWarnings]
|
||||
private void OnSessionStateChanged(ITorchSession session, TorchSessionState newState)
|
||||
{
|
||||
if (newState == TorchSessionState.Unloading || newState == TorchSessionState.Unloaded)
|
||||
|
@@ -18,11 +18,6 @@ namespace Torch.Server.ViewModels
|
||||
private MyConfigDedicated<MyObjectBuilder_SessionSettings> _config;
|
||||
public MyConfigDedicated<MyObjectBuilder_SessionSettings> Model => _config;
|
||||
|
||||
public ConfigDedicatedViewModel() : this(new MyConfigDedicated<MyObjectBuilder_SessionSettings>(""))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public ConfigDedicatedViewModel(MyConfigDedicated<MyObjectBuilder_SessionSettings> configDedicated)
|
||||
{
|
||||
_config = configDedicated;
|
||||
@@ -36,8 +31,7 @@ namespace Torch.Server.ViewModels
|
||||
Validate();
|
||||
|
||||
_config.SessionSettings = SessionSettings;
|
||||
// Never ever
|
||||
//_config.IgnoreLastSession = true;
|
||||
_config.IgnoreLastSession = true;
|
||||
_config.Save(path);
|
||||
}
|
||||
|
||||
@@ -73,8 +67,9 @@ namespace Torch.Server.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public async Task UpdateAllModInfosAsync()
|
||||
public Task UpdateAllModInfosAsync()
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
/*if (!Mods.Any())
|
||||
return;
|
||||
List<MyWorkshopItem> modInfos;
|
||||
|
@@ -85,8 +85,9 @@ namespace Torch.Server.ViewModels
|
||||
/// via the Steam web API.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> UpdateModInfoAsync()
|
||||
public Task<bool> UpdateModInfoAsync()
|
||||
{
|
||||
return Task.FromResult(true);
|
||||
/*if (UgcService.ToLower() == "mod.io")
|
||||
return true;
|
||||
|
||||
@@ -104,7 +105,6 @@ namespace Torch.Server.ViewModels
|
||||
Log.Info("Mod Info successfully retrieved!");
|
||||
FriendlyName = modInfo.Title;
|
||||
Description = modInfo.Description;*/
|
||||
return true;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
|
@@ -3,6 +3,7 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:editors="http://wpfcontrols.com/"
|
||||
mc:Ignorable="d">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
@@ -18,7 +19,7 @@
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Button Grid.Column="1" Content="Send" DockPanel.Dock="Right" Width="50" Margin="5" Click="SendButton_Click"></Button>
|
||||
<TextBox Grid.Column="0" x:Name="Message" Margin="5" KeyDown="Message_OnKeyDown"></TextBox>
|
||||
<editors:AutoCompleteTextBox Grid.Column="0" Margin="5" KeyDown="Message_OnKeyDown" x:Name="MessageBox" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
@@ -28,7 +28,9 @@ using Torch.API.Managers;
|
||||
using Torch.API.Session;
|
||||
using Torch.Managers;
|
||||
using Torch.Server.Managers;
|
||||
using Torch.Server.Views;
|
||||
using VRage.Game;
|
||||
using Color = VRageMath.Color;
|
||||
|
||||
namespace Torch.Server
|
||||
{
|
||||
@@ -38,12 +40,17 @@ namespace Torch.Server
|
||||
public partial class ChatControl : UserControl
|
||||
{
|
||||
private static Logger _log = LogManager.GetCurrentClassLogger();
|
||||
private ITorchServer _server;
|
||||
#pragma warning disable CS0618
|
||||
private ITorchServer _server = (ITorchServer) TorchBase.Instance;
|
||||
#pragma warning restore CS0618
|
||||
private readonly LinkedList<string> _lastMessages = new();
|
||||
private LinkedListNode<string> _currentLastMessageNode;
|
||||
|
||||
public ChatControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.IsVisibleChanged += OnIsVisibleChanged;
|
||||
MessageBox.Provider = new CommandSuggestionsProvider(_server);
|
||||
}
|
||||
|
||||
private void OnIsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
|
||||
@@ -57,8 +64,8 @@ namespace Torch.Server
|
||||
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
Message.Focus();
|
||||
Keyboard.Focus(Message);
|
||||
MessageBox.Focus();
|
||||
Keyboard.Focus(MessageBox);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -160,35 +167,50 @@ namespace Torch.Server
|
||||
|
||||
private void Message_OnKeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == Key.Enter)
|
||||
switch (e.Key)
|
||||
{
|
||||
case Key.Enter:
|
||||
OnMessageEntered();
|
||||
break;
|
||||
case Key.Up:
|
||||
_currentLastMessageNode = _currentLastMessageNode?.Previous ?? _lastMessages.Last;
|
||||
MessageBox.Text = _currentLastMessageNode?.Value ?? string.Empty;
|
||||
break;
|
||||
case Key.Down:
|
||||
_currentLastMessageNode = _currentLastMessageNode?.Next ?? _lastMessages.First;
|
||||
MessageBox.Text = _currentLastMessageNode?.Value ?? string.Empty;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnMessageEntered()
|
||||
{
|
||||
//Can't use Message.Text directly because of object ownership in WPF.
|
||||
var text = Message.Text;
|
||||
var text = MessageBox.Text;
|
||||
if (string.IsNullOrEmpty(text))
|
||||
return;
|
||||
|
||||
var commands = _server.CurrentSession?.Managers.GetManager<Torch.Commands.CommandManager>();
|
||||
if (commands != null && commands.IsCommand(text))
|
||||
{
|
||||
InsertMessage(new TorchChatMessage(TorchBase.Instance.Config.ChatName, text, TorchBase.Instance.Config.ChatColor));
|
||||
InsertMessage(new(_server.Config.ChatName, text, Color.Red, _server.Config.ChatColor));
|
||||
_server.Invoke(() =>
|
||||
{
|
||||
if (!commands.HandleCommandFromServer(text, InsertMessage))
|
||||
{
|
||||
InsertMessage(new TorchChatMessage(TorchBase.Instance.Config.ChatName, "Invalid command.", TorchBase.Instance.Config.ChatColor));
|
||||
return;
|
||||
}
|
||||
if (commands.HandleCommandFromServer(text, InsertMessage)) return;
|
||||
InsertMessage(new(_server.Config.ChatName, "Invalid command.", Color.Red, _server.Config.ChatColor));
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
_server.CurrentSession?.Managers.GetManager<IChatManagerClient>().SendMessageAsSelf(text);
|
||||
}
|
||||
Message.Text = "";
|
||||
if (_currentLastMessageNode is { } && _currentLastMessageNode.Value == text)
|
||||
{
|
||||
_lastMessages.Remove(_currentLastMessageNode);
|
||||
}
|
||||
_lastMessages.AddLast(text);
|
||||
_currentLastMessageNode = null;
|
||||
MessageBox.Text = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -16,9 +16,6 @@
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<UserControl.DataContext>
|
||||
<viewModels:ConfigDedicatedViewModel />
|
||||
</UserControl.DataContext>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
@@ -58,7 +55,7 @@
|
||||
<RowDefinition />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto" x:Name="DediConfigScrollViewer">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
@@ -133,7 +130,7 @@
|
||||
</Grid>
|
||||
<TabControl Grid.Column="1" Margin="3">
|
||||
<TabItem Header="World">
|
||||
<views:PropertyGrid DataContext="{Binding SessionSettings}" IgnoreDisplay ="True" />
|
||||
<views:PropertyGrid DataContext="{Binding SessionSettings}" />
|
||||
</TabItem>
|
||||
<TabItem Header="Torch">
|
||||
<views:PropertyGrid x:Name="TorchSettings" />
|
||||
|
@@ -8,6 +8,8 @@ using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Threading;
|
||||
using Sandbox;
|
||||
using Torch.API;
|
||||
using Torch.API.Managers;
|
||||
using Torch.Server.Annotations;
|
||||
using Torch.Server.Managers;
|
||||
@@ -32,15 +34,26 @@ namespace Torch.Server.Views
|
||||
|
||||
public ConfigControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
_instanceManager = TorchBase.Instance.Managers.GetManager<InstanceManager>();
|
||||
#pragma warning disable CS0618
|
||||
var instance = TorchBase.Instance;
|
||||
#pragma warning restore CS0618
|
||||
instance.GameStateChanged += InstanceOnGameStateChanged;
|
||||
|
||||
_instanceManager = instance.Managers.GetManager<InstanceManager>();
|
||||
_instanceManager.InstanceLoaded += _instanceManager_InstanceLoaded;
|
||||
DataContext = _instanceManager.DedicatedConfig;
|
||||
TorchSettings.DataContext = (TorchConfig)TorchBase.Instance.Config;
|
||||
InitializeComponent();
|
||||
TorchSettings.DataContext = (TorchConfig)instance.Config;
|
||||
// Gets called once all children are loaded
|
||||
Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(ApplyStyles));
|
||||
}
|
||||
|
||||
private void InstanceOnGameStateChanged(MySandboxGame game, TorchGameState newState)
|
||||
{
|
||||
if (newState > TorchGameState.Creating)
|
||||
Dispatcher.InvokeAsync(() => DediConfigScrollViewer.IsEnabled = false);
|
||||
}
|
||||
|
||||
private void CheckValid()
|
||||
{
|
||||
ConfigValid = !_bindingExpressions.Any(x => x.HasError);
|
||||
|
@@ -25,9 +25,6 @@
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<UserControl.DataContext>
|
||||
<viewModels:ConfigDedicatedViewModel />
|
||||
</UserControl.DataContext>
|
||||
<Grid Style="{StaticResource RootGridStyle}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="500px"/>
|
||||
|
@@ -17,11 +17,6 @@
|
||||
<converters:InverseBooleanConverter x:Key="InverseBool"/>
|
||||
</ResourceDictionary>
|
||||
</Window.Resources>
|
||||
<!--
|
||||
<Window.DataContext>
|
||||
<local:TorchServer/>
|
||||
</Window.DataContext>
|
||||
-->
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"></RowDefinition>
|
||||
@@ -63,10 +58,10 @@
|
||||
</StackPanel>
|
||||
<TabControl Grid.Row="2" Height="Auto" x:Name="TabControl" Margin="5,10,5,5">
|
||||
<TabItem Header="Log">
|
||||
<RichTextBox x:Name="ConsoleText" VerticalScrollBarVisibility="Visible" FontFamily="Consolas" IsReadOnly="True" Background="#0c0c0c"/>
|
||||
<views:LogViewerControl x:Name="ConsoleText" Margin="3" />
|
||||
</TabItem>
|
||||
<TabItem Header="Configuration">
|
||||
<Grid IsEnabled="{Binding Path=HasRun, Converter={StaticResource InverseBool}}">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition/>
|
||||
@@ -93,7 +88,7 @@
|
||||
<local:PlayerListControl Grid.Column="1" x:Name="PlayerList" DockPanel.Dock="Right"/>
|
||||
</Grid>
|
||||
</TabItem>
|
||||
<TabItem Header="Entity Manager" x:Name="EntityManagerTab">
|
||||
<TabItem Header="Entity Manager" x:Name="EntityManagerTab" IsEnabled="{Binding Config.EntityManagerEnabled}">
|
||||
</TabItem>
|
||||
<TabItem Header="Plugins">
|
||||
<views:PluginsControl x:Name="Plugins" />
|
||||
|
@@ -14,12 +14,14 @@ using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
using System.Windows.Threading;
|
||||
using NLog;
|
||||
using NLog.Targets.Wrappers;
|
||||
using Sandbox;
|
||||
using Torch.API;
|
||||
using Torch.API.Managers;
|
||||
using Torch.Server.Managers;
|
||||
using Torch.Server.ViewModels;
|
||||
using Torch.Server.Views;
|
||||
using MessageBoxResult = System.Windows.MessageBoxResult;
|
||||
|
||||
@@ -30,23 +32,22 @@ namespace Torch.Server
|
||||
/// </summary>
|
||||
public partial class TorchUI : Window
|
||||
{
|
||||
private TorchServer _server;
|
||||
private TorchConfig _config;
|
||||
|
||||
private bool _autoscrollLog = true;
|
||||
private readonly TorchServer _server;
|
||||
private ITorchConfig Config => _server.Config;
|
||||
|
||||
public TorchUI(TorchServer server)
|
||||
{
|
||||
WindowStartupLocation = WindowStartupLocation.Manual;
|
||||
_config = (TorchConfig)server.Config;
|
||||
Width = _config.WindowWidth;
|
||||
Height = _config.WindowHeight;
|
||||
_server = server;
|
||||
//TODO: data binding for whole server
|
||||
DataContext = server;
|
||||
InitializeComponent();
|
||||
|
||||
AttachConsole();
|
||||
WindowStartupLocation = WindowStartupLocation.Manual;
|
||||
Width = Config.WindowWidth;
|
||||
Height = Config.WindowHeight;
|
||||
InitializeComponent();
|
||||
ConsoleText.FontSize = Config.FontSize;
|
||||
|
||||
Loaded += OnLoaded;
|
||||
|
||||
//Left = _config.WindowPosition.X;
|
||||
//Top = _config.WindowPosition.Y;
|
||||
@@ -56,94 +57,35 @@ namespace Torch.Server
|
||||
Chat.BindServer(server);
|
||||
PlayerList.BindServer(server);
|
||||
Plugins.BindServer(server);
|
||||
LoadConfig((TorchConfig)server.Config);
|
||||
|
||||
Themes.uiSource = this;
|
||||
Themes.SetConfig(_config);
|
||||
Title = $"{_config.InstanceName} - Torch {server.TorchVersion}, SE {server.GameVersion}";
|
||||
|
||||
Loaded += TorchUI_Loaded;
|
||||
if (Config.EntityManagerEnabled)
|
||||
{
|
||||
EntityManagerTab.Content = new EntitiesControl();
|
||||
}
|
||||
|
||||
private void TorchUI_Loaded(object sender, RoutedEventArgs e)
|
||||
Themes.uiSource = this;
|
||||
Themes.SetConfig((TorchConfig) Config);
|
||||
Title = $"{Config.InstanceName} - Torch {server.TorchVersion}, SE {server.GameVersion}";
|
||||
}
|
||||
|
||||
private void OnLoaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var scrollViewer = FindDescendant<ScrollViewer>(ConsoleText);
|
||||
scrollViewer.ScrollChanged += ConsoleText_OnScrollChanged;
|
||||
AttachConsole();
|
||||
}
|
||||
|
||||
private void AttachConsole()
|
||||
{
|
||||
const string target = "wpf";
|
||||
var doc = LogManager.Configuration.FindTargetByName<FlowDocumentTarget>(target)?.Document;
|
||||
if (doc == null)
|
||||
const string targetName = "wpf";
|
||||
var target = LogManager.Configuration.FindTargetByName<LogViewerTarget>(targetName);
|
||||
if (target == null)
|
||||
{
|
||||
var wrapped = LogManager.Configuration.FindTargetByName<WrapperTargetBase>(target);
|
||||
doc = (wrapped?.WrappedTarget as FlowDocumentTarget)?.Document;
|
||||
var wrapped = LogManager.Configuration.FindTargetByName<WrapperTargetBase>(targetName);
|
||||
target = wrapped?.WrappedTarget as LogViewerTarget;
|
||||
}
|
||||
ConsoleText.FontSize = _config.FontSize;
|
||||
ConsoleText.Document = doc ?? new FlowDocument(new Paragraph(new Run("No target!")));
|
||||
ConsoleText.TextChanged += ConsoleText_OnTextChanged;
|
||||
}
|
||||
|
||||
public static T FindDescendant<T>(DependencyObject obj) where T : DependencyObject
|
||||
{
|
||||
if (obj == null) return default(T);
|
||||
int numberChildren = VisualTreeHelper.GetChildrenCount(obj);
|
||||
if (numberChildren == 0) return default(T);
|
||||
|
||||
for (int i = 0; i < numberChildren; i++)
|
||||
{
|
||||
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
|
||||
if (child is T)
|
||||
{
|
||||
return (T)child;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < numberChildren; i++)
|
||||
{
|
||||
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
|
||||
var potentialMatch = FindDescendant<T>(child);
|
||||
if (potentialMatch != default(T))
|
||||
{
|
||||
return potentialMatch;
|
||||
}
|
||||
}
|
||||
|
||||
return default(T);
|
||||
}
|
||||
|
||||
private void ConsoleText_OnTextChanged(object sender, TextChangedEventArgs args)
|
||||
{
|
||||
var textBox = (RichTextBox) sender;
|
||||
if (_autoscrollLog)
|
||||
ConsoleText.ScrollToEnd();
|
||||
}
|
||||
|
||||
private void ConsoleText_OnScrollChanged(object sender, ScrollChangedEventArgs e)
|
||||
{
|
||||
var scrollViewer = (ScrollViewer) sender;
|
||||
if (e.ExtentHeightChange == 0)
|
||||
{
|
||||
// User change.
|
||||
_autoscrollLog = scrollViewer.VerticalOffset == scrollViewer.ScrollableHeight;
|
||||
}
|
||||
}
|
||||
|
||||
public void LoadConfig(TorchConfig config)
|
||||
{
|
||||
if (!Directory.Exists(config.InstancePath))
|
||||
return;
|
||||
|
||||
_config = config;
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
EntityManagerTab.IsEnabled = _config.EntityManagerEnabled;
|
||||
if (_config.EntityManagerEnabled)
|
||||
{
|
||||
EntityManagerTab.Content = new EntitiesControl();
|
||||
}
|
||||
});
|
||||
if (target is null) return;
|
||||
var viewModel = (LogViewerViewModel)ConsoleText.DataContext;
|
||||
target.LogEntries = viewModel.LogEntries;
|
||||
target.TargetContext = SynchronizationContext.Current;
|
||||
}
|
||||
|
||||
private void BtnStart_Click(object sender, RoutedEventArgs e)
|
||||
@@ -176,21 +118,5 @@ namespace Torch.Server
|
||||
|
||||
Process.GetCurrentProcess().Kill();
|
||||
}
|
||||
|
||||
private void BtnRestart_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
//MySandboxGame.Static.Invoke(MySandboxGame.ReloadDedicatedServerSession); use i
|
||||
}
|
||||
|
||||
private void InstancePathBox_OnLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
|
||||
{
|
||||
var name = ((TextBox)sender).Text;
|
||||
|
||||
if (!Directory.Exists(name))
|
||||
return;
|
||||
|
||||
_config.InstancePath = name;
|
||||
_server.Managers.GetManager<InstanceManager>().LoadInstance(_config.InstancePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -19,7 +19,7 @@
|
||||
<!-- <Import Project="$(SolutionDir)\TransformOnBuild.targets" /> -->
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
|
||||
<PackageReference Include="NLog" Version="4.7.13" />
|
||||
<PackageReference Include="NLog" Version="5.0.0-rc2" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@@ -50,11 +50,12 @@ namespace Torch.Commands
|
||||
return !string.IsNullOrEmpty(command) && command[0] == Prefix;
|
||||
}
|
||||
|
||||
public void RegisterCommandModule(Type moduleType, ITorchPlugin plugin = null)
|
||||
public int RegisterCommandModule(Type moduleType, ITorchPlugin plugin = null)
|
||||
{
|
||||
if (!moduleType.IsSubclassOf(typeof(CommandModule)))
|
||||
return;
|
||||
return 0;
|
||||
|
||||
var i = 0;
|
||||
foreach (var method in moduleType.GetMethods())
|
||||
{
|
||||
var commandAttrib = method.GetCustomAttribute<CommandAttribute>();
|
||||
@@ -63,11 +64,14 @@ namespace Torch.Commands
|
||||
|
||||
var command = new Command(plugin, method);
|
||||
var cmdPath = string.Join(".", command.Path);
|
||||
_log.Info($"Registering command '{cmdPath}'");
|
||||
_log.Debug($"Registering command '{cmdPath}'");
|
||||
i++;
|
||||
|
||||
if (!Commands.AddCommand(command))
|
||||
_log.Error($"Command path {cmdPath} is already registered.");
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
public void UnregisterPluginCommands(ITorchPlugin plugin)
|
||||
@@ -78,10 +82,9 @@ namespace Torch.Commands
|
||||
public void RegisterPluginCommands(ITorchPlugin plugin)
|
||||
{
|
||||
var assembly = plugin.GetType().Assembly;
|
||||
foreach (var type in assembly.ExportedTypes)
|
||||
{
|
||||
RegisterCommandModule(type, plugin);
|
||||
}
|
||||
var count = assembly.ExportedTypes.Sum(type => RegisterCommandModule(type, plugin));
|
||||
if (count > 0)
|
||||
_log.Info($"Registered {count} commands from {plugin.Name}");
|
||||
}
|
||||
|
||||
private List<TorchChatMessage> HandleCommandFromServerInternal(string message, Action<TorchChatMessage> subscriber = null)
|
||||
|
@@ -23,6 +23,12 @@ namespace Torch.Managers.PatchManager
|
||||
{
|
||||
private static Action<ILHook, bool> IsAppliedSetter;
|
||||
|
||||
[ReflectedMethodInfo(typeof(MethodBase), nameof(MethodBase.GetMethodFromHandle), Parameters = new[] {typeof(RuntimeMethodHandle)})]
|
||||
private static MethodInfo _getMethodFromHandle = null!;
|
||||
|
||||
[ReflectedMethodInfo(typeof(MethodBase), nameof(MethodBase.GetMethodFromHandle), Parameters = new[] {typeof(RuntimeMethodHandle), typeof(RuntimeTypeHandle)})]
|
||||
private static MethodInfo _getMethodFromHandleGeneric = null!;
|
||||
|
||||
private static readonly Logger _log = LogManager.GetCurrentClassLogger();
|
||||
private readonly MethodBase _method;
|
||||
|
||||
@@ -103,6 +109,7 @@ namespace Torch.Managers.PatchManager
|
||||
public const string INSTANCE_PARAMETER = "__instance";
|
||||
public const string RESULT_PARAMETER = "__result";
|
||||
public const string PREFIX_SKIPPED_PARAMETER = "__prefixSkipped";
|
||||
public const string ORIGINAL_PARAMETER = "__original";
|
||||
public const string LOCAL_PARAMETER = "__local";
|
||||
|
||||
private void SavePatchedMethod(string target)
|
||||
@@ -320,6 +327,24 @@ namespace Torch.Managers.PatchManager
|
||||
yield return new MsilInstruction(OpCodes.Ldarg_0);
|
||||
break;
|
||||
}
|
||||
case ORIGINAL_PARAMETER:
|
||||
{
|
||||
if (!typeof(MethodBase).IsAssignableFrom(param.ParameterType))
|
||||
throw new PatchException($"Original parameter should be assignable to {nameof(MethodBase)}",
|
||||
_method);
|
||||
yield return new MsilInstruction(OpCodes.Ldtoken).InlineValue(_method);
|
||||
if (_method.DeclaringType!.ContainsGenericParameters)
|
||||
{
|
||||
yield return new MsilInstruction(OpCodes.Ldtoken).InlineValue(_method.DeclaringType);
|
||||
yield return new MsilInstruction(OpCodes.Call).InlineValue(_getMethodFromHandleGeneric);
|
||||
}
|
||||
else
|
||||
yield return new MsilInstruction(OpCodes.Call).InlineValue(_getMethodFromHandle);
|
||||
|
||||
if (param.ParameterType != typeof(MethodBase))
|
||||
yield return new MsilInstruction(OpCodes.Castclass).InlineValue(param.ParameterType);
|
||||
break;
|
||||
}
|
||||
case PREFIX_SKIPPED_PARAMETER:
|
||||
{
|
||||
if (param.ParameterType != typeof(bool))
|
||||
|
@@ -9,6 +9,7 @@ using NLog;
|
||||
using Torch.API;
|
||||
using Torch.Managers.PatchManager;
|
||||
using Torch.Utils;
|
||||
using VRage;
|
||||
using VRage.Utils;
|
||||
|
||||
namespace Torch.Patches
|
||||
@@ -42,71 +43,81 @@ namespace Torch.Patches
|
||||
|
||||
[ReflectedMethodInfo(typeof(MyLog), nameof(MyLog.WriteLineAndConsole), Parameters = new[] { typeof(string) })]
|
||||
private static MethodInfo _logWriteLineAndConsole;
|
||||
|
||||
[ReflectedMethodInfo(typeof(MyLog), nameof(MyLog.Init))]
|
||||
private static MethodInfo _logInit;
|
||||
#pragma warning restore 649
|
||||
|
||||
|
||||
public static void Patch(PatchContext context)
|
||||
{
|
||||
context.GetPattern(_logStringBuilder).Prefixes.Add(Method(nameof(PrefixLogStringBuilder)));
|
||||
context.GetPattern(_logFormatted).Prefixes.Add(Method(nameof(PrefixLogFormatted)));
|
||||
context.GetPattern(_logStringBuilder).AddPrefix(nameof(PrefixLogStringBuilder));
|
||||
context.GetPattern(_logFormatted).AddPrefix(nameof(PrefixLogFormatted));
|
||||
|
||||
context.GetPattern(_logWriteLine).Prefixes.Add(Method(nameof(PrefixWriteLine)));
|
||||
context.GetPattern(_logAppendToClosedLog).Prefixes.Add(Method(nameof(PrefixAppendToClosedLog)));
|
||||
context.GetPattern(_logWriteLineAndConsole).Prefixes.Add(Method(nameof(PrefixWriteLineConsole)));
|
||||
context.GetPattern(_logWriteLine).AddPrefix(nameof(PrefixWriteLine));
|
||||
context.GetPattern(_logAppendToClosedLog).AddPrefix(nameof(PrefixAppendToClosedLog));
|
||||
context.GetPattern(_logWriteLineAndConsole).AddPrefix(nameof(PrefixWriteLineConsole));
|
||||
|
||||
context.GetPattern(_logWriteLineException).Prefixes.Add(Method(nameof(PrefixWriteLineException)));
|
||||
context.GetPattern(_logAppendToClosedLogException).Prefixes.Add(Method(nameof(PrefixAppendToClosedLogException)));
|
||||
context.GetPattern(_logWriteLineException).AddPrefix(nameof(PrefixWriteLineException));
|
||||
context.GetPattern(_logAppendToClosedLogException).AddPrefix(nameof(PrefixAppendToClosedLogException));
|
||||
|
||||
context.GetPattern(_logWriteLineOptions).Prefixes.Add(Method(nameof(PrefixWriteLineOptions)));
|
||||
context.GetPattern(_logWriteLineOptions).AddPrefix(nameof(PrefixWriteLineOptions));
|
||||
|
||||
}
|
||||
|
||||
private static MethodInfo Method(string name)
|
||||
{
|
||||
return typeof(KeenLogPatch).GetMethod(name, BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
|
||||
context.GetPattern(_logInit).AddPrefix(nameof(PrefixInit));
|
||||
}
|
||||
|
||||
[ReflectedMethod(Name = "GetIdentByThread")]
|
||||
private static Func<MyLog, int, int> GetIndentByThread = null!;
|
||||
private static Func<MyLog, int, int> _getIndentByThread = null!;
|
||||
|
||||
[ThreadStatic]
|
||||
private static StringBuilder _tmpStringBuilder;
|
||||
[ReflectedGetter(Name = "m_lock")]
|
||||
private static Func<MyLog, FastResourceLock> _lockGetter = null!;
|
||||
|
||||
private static StringBuilder PrepareLog(MyLog log)
|
||||
[ReflectedSetter(Name = "m_enabled")]
|
||||
private static Action<MyLog, bool> _enabledSetter = null!;
|
||||
|
||||
private static int GetIndentByCurrentThread()
|
||||
{
|
||||
_tmpStringBuilder ??= new();
|
||||
using var l = _lockGetter(MyLog.Default).AcquireExclusiveUsing();
|
||||
return _getIndentByThread(MyLog.Default, Environment.CurrentManagedThreadId);
|
||||
}
|
||||
|
||||
_tmpStringBuilder.Clear();
|
||||
var t = GetIndentByThread(log, Environment.CurrentManagedThreadId);
|
||||
private static bool PrefixInit(MyLog __instance, StringBuilder appVersionString)
|
||||
{
|
||||
__instance.WriteLine("Log Started");
|
||||
var byThreadField =
|
||||
typeof(MyLog).GetField("m_indentsByThread", BindingFlags.Instance | BindingFlags.NonPublic)!;
|
||||
var indentsField = typeof(MyLog).GetField("m_indents", BindingFlags.Instance | BindingFlags.NonPublic)!;
|
||||
|
||||
_tmpStringBuilder.Append(' ', t * 3);
|
||||
return _tmpStringBuilder;
|
||||
byThreadField.SetValue(__instance, Activator.CreateInstance(byThreadField.FieldType));
|
||||
indentsField.SetValue(__instance, Activator.CreateInstance(indentsField.FieldType));
|
||||
_enabledSetter(__instance, true);
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool PrefixWriteLine(MyLog __instance, string msg)
|
||||
{
|
||||
if (__instance.LogEnabled)
|
||||
_log.Debug(PrepareLog(__instance).Append(msg));
|
||||
if (__instance.LogEnabled && _log.IsDebugEnabled)
|
||||
_log.Debug($"{" ".PadRight(3 * GetIndentByCurrentThread())}{msg}");
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool PrefixWriteLineConsole(MyLog __instance, string msg)
|
||||
{
|
||||
if (__instance.LogEnabled)
|
||||
_log.Info(PrepareLog(__instance).Append(msg));
|
||||
if (__instance.LogEnabled && _log.IsInfoEnabled)
|
||||
_log.Info($"{" ".PadRight(3 * GetIndentByCurrentThread())}{msg}");
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool PrefixAppendToClosedLog(MyLog __instance, string text)
|
||||
{
|
||||
if (__instance.LogEnabled)
|
||||
_log.Info(PrepareLog(__instance).Append(text));
|
||||
if (__instance.LogEnabled && _log.IsDebugEnabled)
|
||||
_log.Debug($"{" ".PadRight(3 * GetIndentByCurrentThread())}{text}");
|
||||
return false;
|
||||
}
|
||||
private static bool PrefixWriteLineOptions(MyLog __instance, string message, LoggingOptions option)
|
||||
{
|
||||
if (__instance.LogEnabled && __instance.LogFlag(option))
|
||||
_log.Info(PrepareLog(__instance).Append(message));
|
||||
if (__instance.LogEnabled && __instance.LogFlag(option) && _log.IsDebugEnabled)
|
||||
_log.Info($"{" ".PadRight(3 * GetIndentByCurrentThread())}{message}");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -126,22 +137,22 @@ namespace Torch.Patches
|
||||
{
|
||||
if (__instance.LogEnabled)
|
||||
return false;
|
||||
// Sometimes this is called with a pre-formatted string and no args
|
||||
// and causes a crash when the format string contains braces
|
||||
var sb = PrepareLog(__instance);
|
||||
if (args is {Length: > 0})
|
||||
sb.AppendFormat(format, args);
|
||||
else
|
||||
sb.Append(format);
|
||||
|
||||
_log.Log(LogLevelFor(severity), sb);
|
||||
// ReSharper disable once TemplateIsNotCompileTimeConstantProblem
|
||||
_log.Log(new(LogLevelFor(severity), _log.Name, $"{" ".PadRight(3 * GetIndentByCurrentThread())}{string.Format(format, args)}"));
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool PrefixLogStringBuilder(MyLog __instance, MyLogSeverity severity, StringBuilder builder)
|
||||
{
|
||||
if (__instance.LogEnabled)
|
||||
_log.Log(LogLevelFor(severity), PrepareLog(__instance).Append(builder));
|
||||
if (!__instance.LogEnabled) return false;
|
||||
var indent = GetIndentByCurrentThread() * 3;
|
||||
|
||||
// because append resizes every char
|
||||
builder.EnsureCapacity(indent);
|
||||
builder.Append(' ', indent);
|
||||
|
||||
_log.Log(LogLevelFor(severity), builder);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@@ -26,13 +26,16 @@ namespace Torch.Session
|
||||
/// </summary>
|
||||
public MySession KeenSession { get; }
|
||||
|
||||
public IWorld World { get; }
|
||||
|
||||
/// <inheritdoc cref="IDependencyManager"/>
|
||||
public IDependencyManager Managers { get; }
|
||||
|
||||
public TorchSession(ITorchBase torch, MySession keenSession)
|
||||
public TorchSession(ITorchBase torch, MySession keenSession, IWorld world)
|
||||
{
|
||||
Torch = torch;
|
||||
KeenSession = keenSession;
|
||||
World = world;
|
||||
Managers = new DependencyManager(torch.Managers);
|
||||
}
|
||||
|
||||
|
@@ -28,6 +28,9 @@ namespace Torch.Session
|
||||
|
||||
private readonly Dictionary<ulong, MyObjectBuilder_Checkpoint.ModItem> _overrideMods;
|
||||
|
||||
[Dependency]
|
||||
private IInstanceManager _instanceManager = null!;
|
||||
|
||||
public event Action<CollectionChangeEventArgs> OverrideModsChanged;
|
||||
|
||||
/// <summary>
|
||||
@@ -101,15 +104,18 @@ namespace Torch.Session
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_instanceManager.SelectedWorld is null)
|
||||
throw new InvalidOperationException("No valid worlds selected! Please select world first.");
|
||||
|
||||
if (_currentSession != null)
|
||||
{
|
||||
_log.Warn($"Override old torch session {_currentSession.KeenSession.Name}");
|
||||
_currentSession.Detach();
|
||||
}
|
||||
|
||||
_log.Info($"Starting new torch session for {MySession.Static.Name}");
|
||||
_log.Info($"Starting new torch session for {_instanceManager.SelectedWorld.FolderName}");
|
||||
|
||||
_currentSession = new TorchSession(Torch, MySession.Static);
|
||||
_currentSession = new TorchSession(Torch, MySession.Static, _instanceManager.SelectedWorld);
|
||||
SetState(TorchSessionState.Loading);
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -123,11 +129,9 @@ namespace Torch.Session
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_currentSession == null)
|
||||
{
|
||||
_log.Warn("Session loaded event occurred when we don't have a session.");
|
||||
return;
|
||||
}
|
||||
if (_currentSession is null)
|
||||
throw new InvalidOperationException("Session loaded event occurred when we don't have a session.");
|
||||
|
||||
foreach (SessionManagerFactoryDel factory in _factories)
|
||||
{
|
||||
IManager manager = factory(CurrentSession);
|
||||
@@ -135,7 +139,7 @@ namespace Torch.Session
|
||||
CurrentSession.Managers.AddManager(manager);
|
||||
}
|
||||
(CurrentSession as TorchSession)?.Attach();
|
||||
_log.Info($"Loaded torch session for {MySession.Static.Name}");
|
||||
_log.Info($"Loaded torch session for {CurrentSession.World.FolderName}");
|
||||
SetState(TorchSessionState.Loaded);
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -149,12 +153,10 @@ namespace Torch.Session
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_currentSession == null)
|
||||
{
|
||||
_log.Warn("Session unloading event occurred when we don't have a session.");
|
||||
return;
|
||||
}
|
||||
_log.Info($"Unloading torch session for {_currentSession.KeenSession.Name}");
|
||||
if (_currentSession is null)
|
||||
throw new InvalidOperationException("Session loaded event occurred when we don't have a session.");
|
||||
|
||||
_log.Info($"Unloading torch session for {_currentSession.World.FolderName}");
|
||||
SetState(TorchSessionState.Unloading);
|
||||
_currentSession.Detach();
|
||||
}
|
||||
@@ -169,12 +171,10 @@ namespace Torch.Session
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_currentSession == null)
|
||||
{
|
||||
_log.Warn("Session unloading event occurred when we don't have a session.");
|
||||
return;
|
||||
}
|
||||
_log.Info($"Unloaded torch session for {_currentSession.KeenSession.Name}");
|
||||
if (_currentSession is null)
|
||||
throw new InvalidOperationException("Session loaded event occurred when we don't have a session.");
|
||||
|
||||
_log.Info($"Unloaded torch session for {_currentSession.World.FolderName}");
|
||||
SetState(TorchSessionState.Unloaded);
|
||||
_currentSession = null;
|
||||
}
|
||||
|
@@ -20,10 +20,10 @@
|
||||
<!-- <Import Project="$(SolutionDir)\TransformOnBuild.targets" /> -->
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ControlzEx" Version="5.0.1" />
|
||||
<PackageReference Include="InfoOf.Fody" Version="2.1.0" />
|
||||
<PackageReference Include="InfoOf.Fody" Version="2.1.0" PrivateAssets="all" />
|
||||
<PackageReference Include="MahApps.Metro" Version="2.4.9" />
|
||||
<PackageReference Include="MonoMod.RuntimeDetour" Version="22.1.4.3" />
|
||||
<PackageReference Include="NLog" Version="4.7.13" />
|
||||
<PackageReference Include="NLog" Version="5.0.0-rc2" />
|
||||
<PackageReference Include="PropertyChanged.Fody" Version="3.4.0" PrivateAssets="all" />
|
||||
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
||||
<PackageReference Include="Torch.SixLabors.ImageSharp" Version="1.0.0-beta6" />
|
||||
|
Reference in New Issue
Block a user