Merge pull request #431 from theltp/fix/cross-play

final fix for cross-play update
This commit is contained in:
Jimmacle
2021-02-11 21:27:13 -08:00
committed by GitHub
18 changed files with 251 additions and 135 deletions

View File

@@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Torch.API;
namespace Torch namespace Torch
{ {
@@ -24,7 +25,11 @@ namespace Torch
string ChatColor { get; set; } string ChatColor { get; set; }
string TestPlugin { get; set; } string TestPlugin { get; set; }
bool DisconnectOnRestart { get; set; } bool DisconnectOnRestart { get; set; }
int WindowWidth { get; set; }
int WindowHeight { get; set; }
int FontSize { get; set; }
UGCServiceType UgcServiceType { get; set; }
bool Save(string path = null); void Save(string path = null);
} }
} }

View File

@@ -184,8 +184,8 @@
<Compile Include="Session\ITorchSessionManager.cs" /> <Compile Include="Session\ITorchSessionManager.cs" />
<Compile Include="Session\TorchSessionState.cs" /> <Compile Include="Session\TorchSessionState.cs" />
<Compile Include="TorchGameState.cs" /> <Compile Include="TorchGameState.cs" />
<Compile Include="UGCServiceType.cs" />
<Compile Include="Utils\ColorUtils.cs" /> <Compile Include="Utils\ColorUtils.cs" />
<Compile Include="Utils\ModItemUtils.cs" />
<Compile Include="Utils\StringUtils.cs" /> <Compile Include="Utils\StringUtils.cs" />
<Compile Include="WebAPI\JenkinsQuery.cs" /> <Compile Include="WebAPI\JenkinsQuery.cs" />
<Compile Include="WebAPI\PluginQuery.cs" /> <Compile Include="WebAPI\PluginQuery.cs" />

View File

@@ -0,0 +1,8 @@
namespace Torch.API
{
public enum UGCServiceType
{
Steam,
EOS
}
}

View File

@@ -41,8 +41,9 @@ namespace Torch.Server.Commands
[Command("add", "Add a Steam ID to the whitelist.")] [Command("add", "Add a Steam ID to the whitelist.")]
public void Add(ulong steamId) public void Add(ulong steamId)
{ {
if (Config.Whitelist.Add(steamId)) if (!Config.Whitelist.Contains(steamId))
{ {
Config.Whitelist.Add(steamId);
Context.Respond($"Added {steamId} to the whitelist."); Context.Respond($"Added {steamId} to the whitelist.");
Config.Save(); Config.Save();
} }

View File

@@ -21,6 +21,9 @@ namespace Torch.Server
{ {
public class Initializer public class Initializer
{ {
[Obsolete("It's hack. Do not use it!")]
internal static Initializer Instance { get; private set; }
private static readonly Logger Log = LogManager.GetLogger(nameof(Initializer)); private static readonly Logger Log = LogManager.GetLogger(nameof(Initializer));
private bool _init; private bool _init;
private const string STEAMCMD_DIR = "steamcmd"; private const string STEAMCMD_DIR = "steamcmd";
@@ -32,17 +35,17 @@ namespace Torch.Server
login anonymous login anonymous
app_update 298740 app_update 298740
quit"; quit";
private TorchConfig _config;
private TorchServer _server; private TorchServer _server;
private string _basePath; private string _basePath;
public TorchConfig Config => _config; internal Persistent<TorchConfig> ConfigPersistent { get; private set; }
public TorchConfig Config => ConfigPersistent?.Data;
public TorchServer Server => _server; public TorchServer Server => _server;
public Initializer(string basePath) public Initializer(string basePath)
{ {
_basePath = basePath; _basePath = basePath;
Instance = this;
} }
public bool Initialize(string[] args) public bool Initialize(string[] args)
@@ -94,15 +97,15 @@ quit";
File.Copy(havokSource, havokTarget); File.Copy(havokSource, havokTarget);
} }
_config = InitConfig(); InitConfig();
if (!_config.Parse(args)) if (!Config.Parse(args))
return false; return false;
if (!string.IsNullOrEmpty(_config.WaitForPID)) if (!string.IsNullOrEmpty(Config.WaitForPID))
{ {
try try
{ {
var pid = int.Parse(_config.WaitForPID); var pid = int.Parse(Config.WaitForPID);
var waitProc = Process.GetProcessById(pid); var waitProc = Process.GetProcessById(pid);
Log.Info("Continuing in 5 seconds."); Log.Info("Continuing in 5 seconds.");
Log.Warn($"Waiting for process {pid} to close"); Log.Warn($"Waiting for process {pid} to close");
@@ -124,9 +127,9 @@ quit";
public void Run() public void Run()
{ {
_server = new TorchServer(_config); _server = new TorchServer(Config);
if (_config.NoGui) if (Config.NoGui)
{ {
_server.Init(); _server.Init();
_server.Start(); _server.Start();
@@ -134,7 +137,7 @@ quit";
else else
{ {
#if !DEBUG #if !DEBUG
if (!_config.IndependentConsole) if (!Config.IndependentConsole)
{ {
Console.SetOut(TextWriter.Null); Console.SetOut(TextWriter.Null);
NativeMethods.FreeConsole(); NativeMethods.FreeConsole();
@@ -145,9 +148,9 @@ quit";
{ {
_server.Init(); _server.Init();
if (_config.Autostart || _config.TempAutostart) if (Config.Autostart || Config.TempAutostart)
{ {
_config.TempAutostart = false; Config.TempAutostart = false;
_server.Start(); _server.Start();
} }
}); });
@@ -159,22 +162,19 @@ quit";
} }
} }
private TorchConfig InitConfig() private void InitConfig()
{ {
var configName = "Torch.cfg"; var configName = "Torch.cfg";
var configPath = Path.Combine(Directory.GetCurrentDirectory(), configName); var configPath = Path.Combine(Directory.GetCurrentDirectory(), configName);
if (File.Exists(configName)) if (File.Exists(configName))
{ {
Log.Info($"Loading config {configPath}"); Log.Info($"Loading config {configName}");
return TorchConfig.LoadFrom(configPath);
} }
else else
{ {
Log.Info($"Generating default config at {configPath}"); Log.Info($"Generating default config at {configPath}");
var config = new TorchConfig {InstancePath = Path.GetFullPath("Instance")};
config.Save(configPath);
return config;
} }
ConfigPersistent = Persistent<TorchConfig>.Load(configPath);
} }
public static void RunSteamCmd() public static void RunSteamCmd()
@@ -267,13 +267,13 @@ quit";
//MyMiniDump.Write(path, options, MyMiniDump.ExceptionInfo.Present); //MyMiniDump.Write(path, options, MyMiniDump.ExceptionInfo.Present);
} }
LogManager.Flush(); LogManager.Flush();
if (_config.RestartOnCrash) if (Config.RestartOnCrash)
{ {
Console.WriteLine("Restarting in 5 seconds."); Console.WriteLine("Restarting in 5 seconds.");
Thread.Sleep(5000); Thread.Sleep(5000);
var exe = typeof(Program).Assembly.Location; var exe = typeof(Program).Assembly.Location;
_config.WaitForPID = Process.GetCurrentProcess().Id.ToString(); Config.WaitForPID = Process.GetCurrentProcess().Id.ToString();
Process.Start(exe, _config.ToString()); Process.Start(exe, Config.ToString());
} }
else else
{ {

View File

@@ -521,7 +521,6 @@
<Install>false</Install> <Install>false</Install>
</BootstrapperPackage> </BootstrapperPackage>
</ItemGroup> </ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\TransformOnBuild.targets" /> <Import Project="$(SolutionDir)\TransformOnBuild.targets" />
<PropertyGroup> <PropertyGroup>

View File

@@ -1,57 +1,60 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel;
using System.IO; using System.IO;
using System.Runtime.CompilerServices;
using System.Windows; using System.Windows;
using System.Xml.Serialization; using System.Xml.Serialization;
using Newtonsoft.Json; using Newtonsoft.Json;
using NLog; using NLog;
using Torch.API;
using Torch.Views;
using VRage.Game; using VRage.Game;
namespace Torch.Server namespace Torch.Server
{ {
// TODO: redesign this gerbage // TODO: redesign this gerbage
public class TorchConfig : CommandLine, ITorchConfig public class TorchConfig : CommandLine, ITorchConfig, INotifyPropertyChanged
{ {
private static Logger _log = LogManager.GetLogger("Config"); private static Logger _log = LogManager.GetLogger("Config");
public bool ShouldUpdatePlugins => (GetPluginUpdates && !NoUpdate) || ForceUpdate; public bool ShouldUpdatePlugins => (GetPluginUpdates && !NoUpdate) || ForceUpdate;
public bool ShouldUpdateTorch => (GetTorchUpdates && !NoUpdate) || ForceUpdate; public bool ShouldUpdateTorch => (GetTorchUpdates && !NoUpdate) || ForceUpdate;
private string _instancePath = Path.GetFullPath("Instance");
private string _instanceName = "Instance";
private bool _autostart;
private bool _restartOnCrash;
private bool _noGui;
private bool _getPluginUpdates = true;
private bool _getTorchUpdates = true;
private int _tickTimeout = 60;
private bool _localPlugins;
private bool _disconnectOnRestart;
private string _chatName = "Server";
private string _chatColor = "Red";
private bool _enableWhitelist = false;
private List<ulong> _whitelist = new List<ulong>();
private int _windowWidth = 980;
private int _windowHeight = 588;
private bool _independentConsole = false;
private bool _enableAsserts = false;
private int _fontSize = 16;
private UGCServiceType _ugcServiceType = UGCServiceType.Steam;
/// <inheritdoc /> /// <inheritdoc />
[Arg("instancename", "The name of the Torch instance.")] [Arg("instancename", "The name of the Torch instance.")]
public string InstanceName { get; set; } [Display(Name = "Instance Name", Description = "The name of the Torch instance.", GroupName = "Server")]
public string InstanceName { get => _instanceName; set => Set(value, ref _instanceName); }
private string _instancePath;
/// <inheritdoc /> /// <inheritdoc />
[Arg("instancepath", "Server data folder where saves and mods are stored.")] [Arg("instancepath", "Server data folder where saves and mods are stored.")]
[Display(Name = "Instance Path", Description = "Server data folder where saves and mods are stored.", GroupName = "Server")]
public string InstancePath public string InstancePath
{ {
get => _instancePath; get => _instancePath;
set set => Set(value, ref _instancePath);
{
if(String.IsNullOrEmpty(value))
{
_instancePath = value;
return;
}
try
{
if(value.Contains("\""))
throw new InvalidOperationException();
var s = Path.GetFullPath(value);
Console.WriteLine(s); //prevent compiler opitmization - just in case
}
catch (Exception ex)
{
_log.Error(ex, "Invalid path assigned to InstancePath! Please report this immediately! Value: " + value);
//throw;
}
_instancePath = value;
}
} }
/// <inheritdoc /> /// <inheritdoc />
@@ -65,7 +68,8 @@ namespace Torch.Server
/// <summary> /// <summary>
/// Permanent flag to ALWAYS automatically start the server /// Permanent flag to ALWAYS automatically start the server
/// </summary> /// </summary>
public bool Autostart { get; set; } [Display(Name = "Auto Start", Description = "Permanent flag to ALWAYS automatically start the server.", GroupName = "Server")]
public bool Autostart { get => _autostart; set => Set(value, ref _autostart); }
/// <summary> /// <summary>
/// Temporary flag to automatically start the server only on the next run /// Temporary flag to automatically start the server only on the next run
@@ -76,44 +80,69 @@ namespace Torch.Server
/// <inheritdoc /> /// <inheritdoc />
[Arg("restartoncrash", "Automatically restart the server if it crashes.")] [Arg("restartoncrash", "Automatically restart the server if it crashes.")]
public bool RestartOnCrash { get; set; } [Display(Name = "Restart On Crash", Description = "Automatically restart the server if it crashes.", GroupName = "Server")]
public bool RestartOnCrash { get => _restartOnCrash; set => Set(value, ref _restartOnCrash); }
/// <inheritdoc /> /// <inheritdoc />
[Arg("nogui", "Do not show the Torch UI.")] [Arg("nogui", "Do not show the Torch UI.")]
public bool NoGui { get; set; } [Display(Name = "No GUI", Description = "Do not show the Torch UI.", GroupName = "Window")]
public bool NoGui { get => _noGui; set => Set(value, ref _noGui); }
/// <inheritdoc /> /// <inheritdoc />
[XmlIgnore, Arg("waitforpid", "Makes Torch wait for another process to exit.")] [XmlIgnore, Arg("waitforpid", "Makes Torch wait for another process to exit.")]
public string WaitForPID { get; set; } public string WaitForPID { get; set; }
/// <inheritdoc /> /// <inheritdoc />
public bool GetTorchUpdates { get; set; } = true; [Display(Name = "Update Torch", Description = "Check every start for new versions of torch.", GroupName = "Server")]
public bool GetTorchUpdates { get => _getTorchUpdates; set => Set(value, ref _getTorchUpdates); }
/// <inheritdoc /> /// <inheritdoc />
public bool GetPluginUpdates { get; set; } = true; [Display(Name = "Update Plugins", Description = "Check every start for new versions of plugins.", GroupName = "Server")]
public bool GetPluginUpdates { get => _getPluginUpdates; set => Set(value, ref _getPluginUpdates); }
/// <inheritdoc /> /// <inheritdoc />
public int TickTimeout { get; set; } = 60; [Display(Name = "Watchdog Timeout", Description = "Watchdog timeout (in seconds).", GroupName = "Server")]
public int TickTimeout { get => _tickTimeout; set => Set(value, ref _tickTimeout); }
/// <inheritdoc /> /// <inheritdoc />
[Arg("plugins", "Starts Torch with the given plugin GUIDs (space delimited).")] [Arg("plugins", "Starts Torch with the given plugin GUIDs (space delimited).")]
public List<Guid> Plugins { get; set; } = new List<Guid>(); public List<Guid> Plugins { get; set; } = new List<Guid>();
[Arg("localplugins", "Loads all pluhins from disk, ignores the plugins defined in config.")] [Arg("localplugins", "Loads all pluhins from disk, ignores the plugins defined in config.")]
public bool LocalPlugins { get; set; } [Display(Name = "Local Plugins", Description = "Loads all pluhins from disk, ignores the plugins defined in config.", GroupName = "In-Game")]
public bool LocalPlugins { get => _localPlugins; set => Set(value, ref _localPlugins); }
[Arg("disconnect", "When server restarts, all clients are rejected to main menu to prevent auto rejoin")] [Arg("disconnect", "When server restarts, all clients are rejected to main menu to prevent auto rejoin.")]
public bool DisconnectOnRestart { get; set; } [Display(Name = "Auto Disconnect", Description = "When server restarts, all clients are rejected to main menu to prevent auto rejoin.", GroupName = "In-Game")]
public bool DisconnectOnRestart { get => _disconnectOnRestart; set => Set(value, ref _disconnectOnRestart); }
public string ChatName { get; set; } = "Server"; [Display(Name = "Chat Name", Description = "Default name for chat from gui, broadcasts etc..", GroupName = "In-Game")]
public string ChatName { get => _chatName; set => Set(value, ref _chatName); }
public string ChatColor { get; set; } = "Red"; [Display(Name = "Chat Color", Description = "Default color for chat from gui, broadcasts etc.. (Red, Blue, White, Green)", GroupName = "In-Game")]
public string ChatColor { get => _chatColor; set => Set(value, ref _chatColor); }
public bool EnableWhitelist { get; set; } = false; [Display(Name = "Enable Whitelist", Description = "Enable Whitelist to prevent random players join while maintance, tests or other.", GroupName = "In-Game")]
public HashSet<ulong> Whitelist { get; set; } = new HashSet<ulong>(); public bool EnableWhitelist { get => _enableWhitelist; set => Set(value, ref _enableWhitelist); }
public Point WindowSize { get; set; } = new Point(800, 600); [Display(Name = "Whitelist", Description = "Collection of whitelisted steam ids.", GroupName = "In-Game")]
public Point WindowPosition { get; set; } = new Point(); public List<ulong> Whitelist { get => _whitelist; set => Set(value, ref _whitelist); }
[Display(Name = "Width", Description = "Default window width.", GroupName = "Window")]
public int WindowWidth { get => _windowWidth; set => Set(value, ref _windowWidth); }
[Display(Name = "Height", Description = "Default window height", GroupName = "Window")]
public int WindowHeight { get => _windowHeight; set => Set(value, ref _windowHeight); }
[Display(Name = "Font Size", Description = "Font size for logging text box. (default is 16)", GroupName = "Window")]
public int FontSize { get => _fontSize; set => Set(value, ref _fontSize); }
[Display(Name = "UGC Service Type", Description = "Service for downloading mods", GroupName = "Server")]
public UGCServiceType UgcServiceType
{
get => _ugcServiceType;
set => Set(value, ref _ugcServiceType);
}
public string LastUsedTheme { get; set; } = "Torch Theme"; public string LastUsedTheme { get; set; } = "Torch Theme";
@@ -122,64 +151,28 @@ namespace Torch.Server
private bool ShouldSerializeReservedPlayers() => false; private bool ShouldSerializeReservedPlayers() => false;
[Arg("console", "Keeps a separate console window open after the main UI loads.")] [Arg("console", "Keeps a separate console window open after the main UI loads.")]
public bool IndependentConsole { get; set; } = false; [Display(Name = "Independent Console", Description = "Keeps a separate console window open after the main UI loads.", GroupName = "Window")]
public bool IndependentConsole { get => _independentConsole; set => Set(value, ref _independentConsole); }
[XmlIgnore] [XmlIgnore]
[Arg("testplugin", "Path to a plugin to debug. For development use only.")] [Arg("testplugin", "Path to a plugin to debug. For development use only.")]
public string TestPlugin { get; set; } public string TestPlugin { get; set; }
[Arg("asserts", "Enable Keen's assert logging.")] [Arg("asserts", "Enable Keen's assert logging.")]
public bool EnableAsserts { get; set; } = false; [Display(Name = "Enable Asserts", Description = "Enable Keen's assert logging.", GroupName = "Server")]
public bool EnableAsserts { get => _enableAsserts; set => Set(value, ref _enableAsserts); }
[XmlIgnore] public event PropertyChangedEventHandler PropertyChanged;
private string _path;
public TorchConfig() : this("Torch") { } public TorchConfig() { }
public TorchConfig(string instanceName = "Torch", string instancePath = null) protected void Set<T>(T value, ref T field, [CallerMemberName] string callerName = default)
{ {
InstanceName = instanceName; field = value;
InstancePath = instancePath ?? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "SpaceEngineersDedicated"); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(callerName));
} }
public static TorchConfig LoadFrom(string path) // for backward compatibility
{ public void Save(string path = null) => Initializer.Instance?.ConfigPersistent?.Save(path);
try
{
var ser = new XmlSerializer(typeof(TorchConfig));
using (var f = File.OpenRead(path))
{
var config = (TorchConfig)ser.Deserialize(f);
config._path = path;
return config;
}
}
catch (Exception e)
{
_log.Error(e);
return null;
}
}
public bool Save(string path = null)
{
if (path == null)
path = _path;
else
_path = path;
try
{
var ser = new XmlSerializer(typeof(TorchConfig));
using (var f = File.Create(path))
ser.Serialize(f, this);
return true;
}
catch (Exception e)
{
_log.Error(e);
return false;
}
}
} }
} }

View File

@@ -57,13 +57,12 @@ namespace Torch.Server
private bool _simDirty; private bool _simDirty;
/// <inheritdoc /> /// <inheritdoc />
public TorchServer(TorchConfig config = null) public TorchServer(TorchConfig config) : base(config)
{ {
DedicatedInstance = new InstanceManager(this); DedicatedInstance = new InstanceManager(this);
AddManager(DedicatedInstance); AddManager(DedicatedInstance);
AddManager(new EntityControlManager(this)); AddManager(new EntityControlManager(this));
AddManager(new RemoteAPIManager(this)); AddManager(new RemoteAPIManager(this));
Config = config ?? new TorchConfig();
var sessionManager = Managers.GetManager<ITorchSessionManager>(); var sessionManager = Managers.GetManager<ITorchSessionManager>();
sessionManager.AddFactory(x => new MultiplayerManagerDedicated(this)); sessionManager.AddFactory(x => new MultiplayerManagerDedicated(this));

View File

@@ -131,7 +131,15 @@
</ScrollViewer> </ScrollViewer>
<Button Grid.Row="1" Content="Save Config" Margin="3" Click="Save_OnClick" /> <Button Grid.Row="1" Content="Save Config" Margin="3" Click="Save_OnClick" />
</Grid> </Grid>
<views:PropertyGrid Grid.Column="1" Margin="3" DataContext="{Binding SessionSettings}" IgnoreDisplay ="True" /> <TabControl Grid.Column="1" Margin="3">
<TabItem Header="World">
<views:PropertyGrid DataContext="{Binding SessionSettings}" IgnoreDisplay ="True" />
</TabItem>
<TabItem Header="Torch">
<views:PropertyGrid x:Name="TorchSettings" />
</TabItem>
</TabControl>
<GridSplitter Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Stretch" ShowsPreview="True" <GridSplitter Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Stretch" ShowsPreview="True"
Width="2" /> Width="2" />
</Grid> </Grid>

View File

@@ -35,7 +35,7 @@ namespace Torch.Server.Views
_instanceManager = TorchBase.Instance.Managers.GetManager<InstanceManager>(); _instanceManager = TorchBase.Instance.Managers.GetManager<InstanceManager>();
_instanceManager.InstanceLoaded += _instanceManager_InstanceLoaded; _instanceManager.InstanceLoaded += _instanceManager_InstanceLoaded;
DataContext = _instanceManager.DedicatedConfig; DataContext = _instanceManager.DedicatedConfig;
TorchSettings.DataContext = (TorchConfig)TorchBase.Instance.Config;
// Gets called once all children are loaded // Gets called once all children are loaded
Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(ApplyStyles)); Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(ApplyStyles));
} }
@@ -93,6 +93,7 @@ namespace Torch.Server.Views
private void Save_OnClick(object sender, RoutedEventArgs e) private void Save_OnClick(object sender, RoutedEventArgs e)
{ {
_instanceManager.SaveConfig(); _instanceManager.SaveConfig();
((ITorchConfig)TorchSettings.DataContext).Save();
} }
private void ImportConfig_OnClick(object sender, RoutedEventArgs e) private void ImportConfig_OnClick(object sender, RoutedEventArgs e)

View File

@@ -63,7 +63,7 @@
</StackPanel> </StackPanel>
<TabControl Grid.Row="2" Height="Auto" x:Name="TabControl" Margin="5,10,5,5"> <TabControl Grid.Row="2" Height="Auto" x:Name="TabControl" Margin="5,10,5,5">
<TabItem Header="Log"> <TabItem Header="Log">
<RichTextBox x:Name="ConsoleText" VerticalScrollBarVisibility="Visible" FontFamily="Consolas" IsReadOnly="True"/> <RichTextBox x:Name="ConsoleText" VerticalScrollBarVisibility="Visible" FontFamily="Consolas" IsReadOnly="True" Background="#0c0c0c"/>
</TabItem> </TabItem>
<TabItem Header="Configuration"> <TabItem Header="Configuration">
<Grid IsEnabled="{Binding Path=HasRun, Converter={StaticResource InverseBool}}"> <Grid IsEnabled="{Binding Path=HasRun, Converter={StaticResource InverseBool}}">

View File

@@ -36,10 +36,10 @@ namespace Torch.Server
public TorchUI(TorchServer server) public TorchUI(TorchServer server)
{ {
WindowStartupLocation = WindowStartupLocation.CenterScreen; WindowStartupLocation = WindowStartupLocation.Manual;
Width = 800;
Height = 600;
_config = (TorchConfig)server.Config; _config = (TorchConfig)server.Config;
Width = _config.WindowWidth;
Height = _config.WindowHeight;
_server = server; _server = server;
//TODO: data binding for whole server //TODO: data binding for whole server
DataContext = server; DataContext = server;
@@ -79,6 +79,7 @@ namespace Torch.Server
var wrapped = LogManager.Configuration.FindTargetByName<WrapperTargetBase>(target); var wrapped = LogManager.Configuration.FindTargetByName<WrapperTargetBase>(target);
doc = (wrapped?.WrappedTarget as FlowDocumentTarget)?.Document; doc = (wrapped?.WrappedTarget as FlowDocumentTarget)?.Document;
} }
ConsoleText.FontSize = _config.FontSize;
ConsoleText.Document = doc ?? new FlowDocument(new Paragraph(new Run("No target!"))); ConsoleText.Document = doc ?? new FlowDocument(new Paragraph(new Run("No target!")));
ConsoleText.TextChanged += ConsoleText_OnTextChanged; ConsoleText.TextChanged += ConsoleText_OnTextChanged;
} }

View File

@@ -0,0 +1,50 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using NLog;
using Sandbox;
using Sandbox.Engine.Networking;
using Torch.Managers.PatchManager;
using Torch.Managers.PatchManager.MSIL;
using Torch.Utils;
using VRage.Game;
namespace Torch.Patches
{
[PatchShim]
internal class ModsDownloadingPatch
{
private static readonly Logger _log = LogManager.GetCurrentClassLogger();
#pragma warning disable 649
[ReflectedMethodInfo(typeof(MyWorkshop), nameof(MyWorkshop.DownloadWorldModsBlocking))]
private readonly static MethodInfo _downloadWorldModsBlockingMethod;
#pragma warning restore 649
public static void Patch(PatchContext ctx)
{
_log.Info("Patching mods downloading");
var pattern = ctx.GetPattern(_downloadWorldModsBlockingMethod);
pattern.Suffixes
.Add(typeof(ModsDownloadingPatch).GetMethod(nameof(Postfix)));
pattern.Prefixes.Add(typeof(ModsDownloadingPatch).GetMethod(nameof(Prefix)));
}
public static void Prefix(ref List<MyObjectBuilder_Checkpoint.ModItem> mods)
{
var serviceName = MyGameService.GetDefaultUGC().ServiceName;
mods = mods?.Select(b => {
b.PublishedServiceName = serviceName;
return b;
}).ToList();
}
public static void Postfix(MyWorkshop.ResultData __result)
{
if (!__result.Success)
{
_log.Warn("Missing Mods:");
__result.MismatchMods.ForEach(b => _log.Info($"\t{b.Title} : {b.Id}"));
}
}
}
}

View File

@@ -141,6 +141,10 @@
<HintPath>..\GameBinaries\VRage.Dedicated.dll</HintPath> <HintPath>..\GameBinaries\VRage.Dedicated.dll</HintPath>
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
<Reference Include="VRage.EOS, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
<HintPath>..\GameBinaries\VRage.EOS.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Game"> <Reference Include="VRage.Game">
<HintPath>..\GameBinaries\VRage.Game.dll</HintPath> <HintPath>..\GameBinaries\VRage.Game.dll</HintPath>
<Private>False</Private> <Private>False</Private>
@@ -161,6 +165,10 @@
<HintPath>..\GameBinaries\VRage.Math.dll</HintPath> <HintPath>..\GameBinaries\VRage.Math.dll</HintPath>
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
<Reference Include="VRage.Mod.Io, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
<HintPath>..\GameBinaries\VRage.Mod.Io.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Platform.Windows, Culture=neutral, PublicKeyToken=null"> <Reference Include="VRage.Platform.Windows, Culture=neutral, PublicKeyToken=null">
<HintPath>..\GameBinaries\VRage.Platform.Windows.dll</HintPath> <HintPath>..\GameBinaries\VRage.Platform.Windows.dll</HintPath>
<Private>False</Private> <Private>False</Private>
@@ -238,6 +246,7 @@
<Compile Include="Patches\GameAnalyticsPatch.cs" /> <Compile Include="Patches\GameAnalyticsPatch.cs" />
<Compile Include="Patches\GameStatePatchShim.cs" /> <Compile Include="Patches\GameStatePatchShim.cs" />
<Compile Include="Patches\KeenLogPatch.cs" /> <Compile Include="Patches\KeenLogPatch.cs" />
<Compile Include="Patches\ModsDownloadingPatch.cs" />
<Compile Include="Patches\ObjectFactoryInitPatch.cs" /> <Compile Include="Patches\ObjectFactoryInitPatch.cs" />
<Compile Include="Patches\PhysicsMemoryPatch.cs" /> <Compile Include="Patches\PhysicsMemoryPatch.cs" />
<Compile Include="Patches\SessionDownloadPatch.cs" /> <Compile Include="Patches\SessionDownloadPatch.cs" />
@@ -265,6 +274,7 @@
<Compile Include="Managers\UpdateManager.cs" /> <Compile Include="Managers\UpdateManager.cs" />
<Compile Include="Persistent.cs" /> <Compile Include="Persistent.cs" />
<Compile Include="Plugins\PluginManifest.cs" /> <Compile Include="Plugins\PluginManifest.cs" />
<Compile Include="Utils\ModItemUtils.cs" />
<Compile Include="Utils\SteamWorkshopTools\KeyValueExtensions.cs" /> <Compile Include="Utils\SteamWorkshopTools\KeyValueExtensions.cs" />
<Compile Include="Utils\MiscExtensions.cs" /> <Compile Include="Utils\MiscExtensions.cs" />
<Compile Include="Utils\Reflected\ReflectedEventReplaceAttribute.cs" /> <Compile Include="Utils\Reflected\ReflectedEventReplaceAttribute.cs" />

View File

@@ -131,13 +131,14 @@ namespace Torch
/// ///
/// </summary> /// </summary>
/// <exception cref="InvalidOperationException">Thrown if a TorchBase instance already exists.</exception> /// <exception cref="InvalidOperationException">Thrown if a TorchBase instance already exists.</exception>
protected TorchBase() protected TorchBase(ITorchConfig config)
{ {
RegisterCoreAssembly(GetType().Assembly); RegisterCoreAssembly(GetType().Assembly);
if (Instance != null) if (Instance != null)
throw new InvalidOperationException("A TorchBase instance already exists."); throw new InvalidOperationException("A TorchBase instance already exists.");
Instance = this; Instance = this;
Config = config;
var versionString = Assembly.GetEntryAssembly() var versionString = Assembly.GetEntryAssembly()
.GetCustomAttribute<AssemblyInformationalVersionAttribute>() .GetCustomAttribute<AssemblyInformationalVersionAttribute>()

View File

@@ -11,6 +11,16 @@ namespace Torch.Utils
} }
//because KEEEN! //because KEEEN!
public static string GetDefaultServiceName() => "Steam"; public static string GetDefaultServiceName()
{
try
{
return MyGameService.GetDefaultUGC().ServiceName;
}
catch
{
return TorchBase.Instance.Config.UgcServiceType.ToString();
}
}
} }
} }

View File

@@ -23,15 +23,18 @@ using Sandbox.Graphics.GUI;
using SpaceEngineers.Game; using SpaceEngineers.Game;
using SpaceEngineers.Game.GUI; using SpaceEngineers.Game.GUI;
using Steamworks; using Steamworks;
using Torch.API;
using Torch.Utils; using Torch.Utils;
using VRage; using VRage;
using VRage.Audio; using VRage.Audio;
using VRage.Dedicated; using VRage.Dedicated;
using VRage.EOS;
using VRage.FileSystem; using VRage.FileSystem;
using VRage.Game; using VRage.Game;
using VRage.Game.ObjectBuilder; using VRage.Game.ObjectBuilder;
using VRage.Game.SessionComponents; using VRage.Game.SessionComponents;
using VRage.GameServices; using VRage.GameServices;
using VRage.Mod.Io;
using VRage.Plugins; using VRage.Plugins;
using VRage.Scripting; using VRage.Scripting;
using VRage.Steam; using VRage.Steam;
@@ -157,17 +160,44 @@ namespace Torch
MyFileSystem.Reset(); MyFileSystem.Reset();
MyInitializer.InvokeBeforeRun(_appSteamId, _appName, _userDataPath); MyInitializer.InvokeBeforeRun(_appSteamId, _appName, _userDataPath);
_log.Info("Initializing services");
var service = MySteamGameService.Create(true, _appSteamId);
//Type.GetType("VRage.Steam.MySteamService, VRage.Steam").GetProperty("IsActive").GetSetMethod(true).Invoke(service, new object[] {SteamAPI.Init()}); //Type.GetType("VRage.Steam.MySteamService, VRage.Steam").GetProperty("IsActive").GetSetMethod(true).Invoke(service, new object[] {SteamAPI.Init()});
_log.Info("Initializing UGC services");
IMyGameService service;
IMyUGCService serviceInstance;
if (TorchBase.Instance.Config.UgcServiceType == UGCServiceType.Steam)
{
service = MySteamGameService.Create(dedicated, _appSteamId);
serviceInstance = MySteamUgcService.Create(_appSteamId, service);
MySteamGameService.InitNetworking(dedicated, service, (MyServerDiscoveryAggregator) MyGameService.ServerDiscovery);
}
else
{
service = MyEOSService.Create();
serviceInstance = MyModIoService.Create(service, "spaceengineers", "264",
"1fb4489996a5e8ffc6ec1135f9985b5b", "331", "f2b64abe55452252b030c48adc0c1f0e",
MyPlatformGameSettings.UGC_TEST_ENVIRONMENT);
MyEOSService.InitNetworking(dedicated,
dedicated ? MyPerServerSettings.GameDSName : MyPerServerSettings.GameNameSafe, service,
"xyza7891A4WeGrpP85BTlBa3BSfUEABN", "ZdHZVevSVfIajebTnTmh5MVi3KPHflszD9hJB7mRkgg",
"24b1cd652a18461fa9b3d533ac8d6b5b", "1958fe26c66d4151a327ec162e4d49c8",
"07c169b3b641401496d352cad1c905d6", "https://retail.epicgames.com/", MyEOSService.CreatePlatform(),
MySandboxGame.ConfigDedicated.VerboseNetworkLogging, null, null, null);
var mockingInventory = new MyMockingInventory(service);
MyServiceManager.Instance.AddService<IMyInventoryService>(mockingInventory);
}
MyServiceManager.Instance.AddService<IMyGameService>(service); MyServiceManager.Instance.AddService<IMyGameService>(service);
var serviceInstance = MySteamUgcService.Create(_appSteamId, service);
MyServiceManager.Instance.AddService<IMyUGCService>(serviceInstance); MyServiceManager.Instance.AddService<IMyUGCService>(serviceInstance);
MyGameService.WorkshopService.AddAggregate(serviceInstance);
_log.Info("Initializing services");
MyServiceManager.Instance.AddService(new MyNullMicrophone()); MyServiceManager.Instance.AddService(new MyNullMicrophone());
MySteamGameService.InitNetworking(dedicated, service, (MyServerDiscoveryAggregator) MyGameService.ServerDiscovery);
if (!MyGameService.HasGameServer) if (!MyGameService.HasGameServer)
{ {
_log.Warn("Steam service is not running! Please reinstall dedicated server."); _log.Warn("Network service is not running! Please reinstall dedicated server.");
return; return;
} }
@@ -291,7 +321,7 @@ namespace Torch
return; return;
} }
MyObjectBuilder_Checkpoint checkpoint = MyLocalCache.LoadCheckpoint(sessionPath, out ulong checkpointSize); MyObjectBuilder_Checkpoint checkpoint = MyLocalCache.LoadCheckpoint(sessionPath, out ulong checkpointSize);
if (MySession.IsCompatibleVersion(checkpoint)) /*if (MySession.IsCompatibleVersion(checkpoint))
{ {
var downloadResult = MyWorkshop.DownloadWorldModsBlocking(checkpoint.Mods.Select(b => var downloadResult = MyWorkshop.DownloadWorldModsBlocking(checkpoint.Mods.Select(b =>
{ {
@@ -314,7 +344,7 @@ namespace Torch
} }
else else
MyLog.Default.WriteLineAndConsole(MyTexts.Get(MyCommonTexts.DialogTextIncompatibleWorldVersion) MyLog.Default.WriteLineAndConsole(MyTexts.Get(MyCommonTexts.DialogTextIncompatibleWorldVersion)
.ToString()); .ToString());*/
} }
private void DoJoinSession(ulong lobbyId) private void DoJoinSession(ulong lobbyId)

View File

@@ -81,7 +81,7 @@ namespace Torch.Views
//If not found and IgnoreDisplay is not set, fall back to system DisplayAttribute //If not found and IgnoreDisplay is not set, fall back to system DisplayAttribute
if (a == null && !IgnoreDisplay) if (a == null && !IgnoreDisplay)
a = property.GetCustomAttribute<System.ComponentModel.DataAnnotations.DisplayAttribute>(); a = property.GetCustomAttribute<System.ComponentModel.DataAnnotations.DisplayAttribute>();
if (a?.Visible == false) if (!IgnoreDisplay && a == null || a?.Visible == false)
continue; continue;
descriptors[property] = a; descriptors[property] = a;
string category = a?.GroupName ?? "Misc"; string category = a?.GroupName ?? "Misc";