From 43adecaf990718c5f211aa194fdd4da4fbfc614d Mon Sep 17 00:00:00 2001 From: Brant Martin Date: Thu, 22 Aug 2019 13:25:53 -0400 Subject: [PATCH 1/9] Publictest (#335) * Fix compiler errors * Fix Jenkins * Build public test as Release * Fix more things * Oops * Remove obsolete code * Fix GameStatePatchShim --- Jenkins/jenkins-grab-se.ps1 | 4 +- Jenkinsfile | 4 +- Torch.API/WebAPI/JenkinsQuery.cs | 3 - Torch.Server/Initializer.cs | 2 +- Torch.Server/Managers/InstanceManager.cs | 10 - .../Patches/WorldLoadExceptionPatch.cs | 48 +++ Torch.Server/Torch.Server.csproj | 12 +- Torch.Server/TorchConfig.cs | 4 - Torch.Server/TorchServer.cs | 1 + .../NetworkManager/NetworkHandlerBase.cs | 254 ----------- .../Managers/NetworkManager/NetworkManager.cs | 10 +- .../NetworkManager_Deprecated.cs | 407 ------------------ .../Managers/PatchManager/DecoratedMethod.cs | 2 +- Torch/Managers/ScriptingManager.cs | 54 --- Torch/Managers/UpdateManager.cs | 2 +- Torch/Patches/GameAnalyticsPatch.cs | 6 +- Torch/Patches/GameStatePatchShim.cs | 2 +- Torch/Patches/TorchAsyncSaving.cs | 1 + Torch/Torch.csproj | 3 - Torch/TorchBase.cs | 3 +- Torch/VRageGame.cs | 4 - Torch/Views/PropertyGrid.xaml.cs | 1 - 22 files changed, 68 insertions(+), 769 deletions(-) create mode 100644 Torch.Server/Patches/WorldLoadExceptionPatch.cs delete mode 100644 Torch/Managers/NetworkManager/NetworkHandlerBase.cs delete mode 100644 Torch/Managers/NetworkManager/NetworkManager_Deprecated.cs delete mode 100644 Torch/Managers/ScriptingManager.cs diff --git a/Jenkins/jenkins-grab-se.ps1 b/Jenkins/jenkins-grab-se.ps1 index 10d4105..5699e3d 100644 --- a/Jenkins/jenkins-grab-se.ps1 +++ b/Jenkins/jenkins-grab-se.ps1 @@ -1,6 +1,6 @@ pushd -$steamData = "C:/Steam/Data/" +$steamData = "C:/Steam/Data-playtest/" $steamCMDPath = "C:/Steam/steamcmd/" $steamCMDZip = "C:/Steam/steamcmd.zip" @@ -17,6 +17,6 @@ if (!(Test-Path $steamCMDPath)) { } cd "$steamData" -& "$steamCMDPath/steamcmd.exe" "+login anonymous" "+force_install_dir $steamData" "+app_update 298740" "+quit" +& "$steamCMDPath/steamcmd.exe" "+login anonymous" "+force_install_dir $steamData" "+app_update 298740 -beta publictest -betapassword nt8WuDw9kdvE validate" "+quit" popd diff --git a/Jenkinsfile b/Jenkinsfile index 7481efd..14b2267 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -22,7 +22,7 @@ node { stage('Acquire SE') { bat 'powershell -File Jenkins/jenkins-grab-se.ps1' bat 'IF EXIST GameBinaries RMDIR GameBinaries' - bat 'mklink /J GameBinaries "C:/Steam/Data/DedicatedServer64/"' + bat 'mklink /J GameBinaries "C:/Steam/Data-playtest/DedicatedServer64/"' } stage('Acquire NuGet Packages') { @@ -31,7 +31,7 @@ node { stage('Build') { currentBuild.description = bat(returnStdout: true, script: '@powershell -File Versioning/version.ps1').trim() - if (env.BRANCH_NAME == "master" || env.BRANCH_NAME == "Patron") { + if (env.BRANCH_NAME == "master" || env.BRANCH_NAME == "Patron" || env.BRANCH_NAME == "publictest") { buildMode = "Release" } else { buildMode = "Debug" diff --git a/Torch.API/WebAPI/JenkinsQuery.cs b/Torch.API/WebAPI/JenkinsQuery.cs index 5c9ea1c..d4620e5 100644 --- a/Torch.API/WebAPI/JenkinsQuery.cs +++ b/Torch.API/WebAPI/JenkinsQuery.cs @@ -30,9 +30,6 @@ namespace Torch.API.WebAPI public async Task GetLatestVersion(string branch) { -#if DEBUG - branch = "master"; -#endif var h = await _client.GetAsync(string.Format(BRANCH_QUERY, branch)); if (!h.IsSuccessStatusCode) { diff --git a/Torch.Server/Initializer.cs b/Torch.Server/Initializer.cs index e152373..23d89e0 100644 --- a/Torch.Server/Initializer.cs +++ b/Torch.Server/Initializer.cs @@ -31,7 +31,7 @@ namespace Torch.Server private const string RUNSCRIPT = @"force_install_dir ../ login anonymous -app_update 298740 +app_update 298740 -beta publictest -betapassword nt8WuDw9kdvE validate quit"; private TorchConfig _config; diff --git a/Torch.Server/Managers/InstanceManager.cs b/Torch.Server/Managers/InstanceManager.cs index 82ad278..01ff765 100644 --- a/Torch.Server/Managers/InstanceManager.cs +++ b/Torch.Server/Managers/InstanceManager.cs @@ -198,16 +198,6 @@ namespace Torch.Server.Managers public void SaveConfig() { - var cf = Torch.Config as TorchConfig; - if (cf?.ReservedPlayers?.Count > 0) - { - foreach (var res in cf.ReservedPlayers) - { - if (!DedicatedConfig.Reserved.Contains(res)) - DedicatedConfig.Reserved.Add(res); - } - } - DedicatedConfig.Save(Path.Combine(Torch.Config.InstancePath, CONFIG_NAME)); Log.Info("Saved dedicated config."); diff --git a/Torch.Server/Patches/WorldLoadExceptionPatch.cs b/Torch.Server/Patches/WorldLoadExceptionPatch.cs new file mode 100644 index 0000000..a1cbcaf --- /dev/null +++ b/Torch.Server/Patches/WorldLoadExceptionPatch.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Reflection.Emit; +using NLog; +using Sandbox; +using Torch.Managers.PatchManager; +using Torch.Managers.PatchManager.MSIL; + +namespace Torch.Patches +{ + /// + /// Patches MySandboxGame.InitQuickLaunch to rethrow exceptions caught during session load. + /// + [PatchShim] + public static class WorldLoadExceptionPatch + { + private static readonly ILogger _log = LogManager.GetCurrentClassLogger(); + + public static void Patch(PatchContext ctx) + { + ctx.GetPattern(typeof(MySandboxGame).GetMethod("InitQuickLaunch", BindingFlags.Instance | BindingFlags.NonPublic)) + .Transpilers.Add(typeof(WorldLoadExceptionPatch).GetMethod(nameof(Transpile), BindingFlags.Static | BindingFlags.NonPublic)); + } + + private static IEnumerable Transpile(IEnumerable method) + { + var msil = method.ToList(); + for (var i = 0; i < msil.Count; i++) + { + if (msil[i].TryCatchOperations.All(x => x.Type != MsilTryCatchOperationType.BeginClauseBlock)) + continue; + + for (; i < msil.Count; i++) + { + if (msil[i].OpCode != OpCodes.Leave) + continue; + + msil[i] = new MsilInstruction(OpCodes.Rethrow); + break; + } + } + return msil; + } + } +} \ No newline at end of file diff --git a/Torch.Server/Torch.Server.csproj b/Torch.Server/Torch.Server.csproj index 1ebb566..6695434 100644 --- a/Torch.Server/Torch.Server.csproj +++ b/Torch.Server/Torch.Server.csproj @@ -208,15 +208,8 @@ ..\GameBinaries\VRage.Math.dll False - - False - ..\GameBinaries\VRage.Native.dll - False - - - False - ..\GameBinaries\VRage.OpenVRWrapper.dll - False + + ..\GameBinaries\VRage.Platform.Windows.dll False @@ -257,6 +250,7 @@ + diff --git a/Torch.Server/TorchConfig.cs b/Torch.Server/TorchConfig.cs index 7b3717b..a985589 100644 --- a/Torch.Server/TorchConfig.cs +++ b/Torch.Server/TorchConfig.cs @@ -109,10 +109,6 @@ namespace Torch.Server public string LastUsedTheme { get; set; } = "Torch Theme"; - //TODO: REMOVE ME BY JULY 2019 - [Obsolete("Use vanilla reserved slot config")] - public HashSet ReservedPlayers { get; set; } = new HashSet(); - //Prevent reserved players being written to disk, but allow it to be read //remove this when ReservedPlayers is removed private bool ShouldSerializeReservedPlayers() => false; diff --git a/Torch.Server/TorchServer.cs b/Torch.Server/TorchServer.cs index d017354..0f593f3 100644 --- a/Torch.Server/TorchServer.cs +++ b/Torch.Server/TorchServer.cs @@ -27,6 +27,7 @@ using VRage; using VRage.Dedicated; using VRage.Dedicated.RemoteAPI; using VRage.GameServices; +using VRage.Scripting; using VRage.Steam; using Timer = System.Threading.Timer; diff --git a/Torch/Managers/NetworkManager/NetworkHandlerBase.cs b/Torch/Managers/NetworkManager/NetworkHandlerBase.cs deleted file mode 100644 index 3add688..0000000 --- a/Torch/Managers/NetworkManager/NetworkHandlerBase.cs +++ /dev/null @@ -1,254 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Threading.Tasks; -using VRage; -using VRage.Library.Collections; -using VRage.Network; -using VRage.Serialization; - -namespace Torch.Managers -{ - [Obsolete("The entire network intercept system is deprecated. Please use method patches instead.")] - public abstract class NetworkHandlerBase - { - /// - /// Check the method name and do unit tests on parameters in here. - /// - /// - /// - [Obsolete("The entire network intercept system is deprecated. Please use method patches instead.")] - public abstract bool CanHandle(CallSite site); - - /// - /// Performs action on network packet. Return value of true means the packet has been handled, and will not be passed on to the game server. - /// - /// - /// - /// - /// - /// - /// - [Obsolete("The entire network intercept system is deprecated. Please use method patches instead.")] - public abstract bool Handle(ulong remoteUserId, CallSite site, BitStream stream, object obj, MyPacket packet); - - /// - /// Extracts method arguments from the bitstream or packs them back in, depending on stream read mode. - /// - /// - /// - /// - /// - [Obsolete("The entire network intercept system is deprecated. Please use method patches instead.")] - public void Serialize(MethodInfo info, BitStream stream, ref T1 arg1) - { - var s1 = MyFactory.GetSerializer(); - - var args = info.GetParameters(); - var info1 = MySerializeInfo.CreateForParameter(args, 0); - - if (stream.Reading) - { - MySerializationHelpers.CreateAndRead(stream, out arg1, s1, info1); - } - else - { - MySerializationHelpers.Write(stream, ref arg1, s1, info1); - } - } - - [Obsolete("The entire network intercept system is deprecated. Please use method patches instead.")] - public void Serialize(MethodInfo info, BitStream stream, ref T1 arg1, ref T2 arg2) - { - var s1 = MyFactory.GetSerializer(); - var s2 = MyFactory.GetSerializer(); - - var args = info.GetParameters(); - var info1 = MySerializeInfo.CreateForParameter(args, 0); - var info2 = MySerializeInfo.CreateForParameter(args, 1); - - if (stream.Reading) - { - MySerializationHelpers.CreateAndRead(stream, out arg1, s1, info1); - MySerializationHelpers.CreateAndRead(stream, out arg2, s2, info2); - } - else - { - MySerializationHelpers.Write(stream, ref arg1, s1, info1); - MySerializationHelpers.Write(stream, ref arg2, s2, info2); - } - } - - [Obsolete("The entire network intercept system is deprecated. Please use method patches instead.")] - public void Serialize(MethodInfo info, BitStream stream, ref T1 arg1, ref T2 arg2, ref T3 arg3) - { - var s1 = MyFactory.GetSerializer(); - var s2 = MyFactory.GetSerializer(); - var s3 = MyFactory.GetSerializer(); - - var args = info.GetParameters(); - var info1 = MySerializeInfo.CreateForParameter(args, 0); - var info2 = MySerializeInfo.CreateForParameter(args, 1); - var info3 = MySerializeInfo.CreateForParameter(args, 2); - - if (stream.Reading) - { - MySerializationHelpers.CreateAndRead(stream, out arg1, s1, info1); - MySerializationHelpers.CreateAndRead(stream, out arg2, s2, info2); - MySerializationHelpers.CreateAndRead(stream, out arg3, s3, info3); - } - else - { - MySerializationHelpers.Write(stream, ref arg1, s1, info1); - MySerializationHelpers.Write(stream, ref arg2, s2, info2); - MySerializationHelpers.Write(stream, ref arg3, s3, info3); - } - } - - [Obsolete("The entire network intercept system is deprecated. Please use method patches instead.")] - public void Serialize(MethodInfo info, BitStream stream, ref T1 arg1, ref T2 arg2, ref T3 arg3, ref T4 arg4) - { - var s1 = MyFactory.GetSerializer(); - var s2 = MyFactory.GetSerializer(); - var s3 = MyFactory.GetSerializer(); - var s4 = MyFactory.GetSerializer(); - - var args = info.GetParameters(); - var info1 = MySerializeInfo.CreateForParameter(args, 0); - var info2 = MySerializeInfo.CreateForParameter(args, 1); - var info3 = MySerializeInfo.CreateForParameter(args, 2); - var info4 = MySerializeInfo.CreateForParameter(args, 3); - - if (stream.Reading) - { - MySerializationHelpers.CreateAndRead(stream, out arg1, s1, info1); - MySerializationHelpers.CreateAndRead(stream, out arg2, s2, info2); - MySerializationHelpers.CreateAndRead(stream, out arg3, s3, info3); - MySerializationHelpers.CreateAndRead(stream, out arg4, s4, info4); - } - else - { - MySerializationHelpers.Write(stream, ref arg1, s1, info1); - MySerializationHelpers.Write(stream, ref arg2, s2, info2); - MySerializationHelpers.Write(stream, ref arg3, s3, info3); - MySerializationHelpers.Write(stream, ref arg4, s4, info4); - } - } - - [Obsolete("The entire network intercept system is deprecated. Please use method patches instead.")] - public void Serialize(MethodInfo info, BitStream stream, ref T1 arg1, ref T2 arg2, ref T3 arg3, ref T4 arg4, ref T5 arg5) - { - var s1 = MyFactory.GetSerializer(); - var s2 = MyFactory.GetSerializer(); - var s3 = MyFactory.GetSerializer(); - var s4 = MyFactory.GetSerializer(); - var s5 = MyFactory.GetSerializer(); - - var args = info.GetParameters(); - var info1 = MySerializeInfo.CreateForParameter(args, 0); - var info2 = MySerializeInfo.CreateForParameter(args, 1); - var info3 = MySerializeInfo.CreateForParameter(args, 2); - var info4 = MySerializeInfo.CreateForParameter(args, 3); - var info5 = MySerializeInfo.CreateForParameter(args, 4); - - if (stream.Reading) - { - MySerializationHelpers.CreateAndRead(stream, out arg1, s1, info1); - MySerializationHelpers.CreateAndRead(stream, out arg2, s2, info2); - MySerializationHelpers.CreateAndRead(stream, out arg3, s3, info3); - MySerializationHelpers.CreateAndRead(stream, out arg4, s4, info4); - MySerializationHelpers.CreateAndRead(stream, out arg5, s5, info5); - } - else - { - MySerializationHelpers.Write(stream, ref arg1, s1, info1); - MySerializationHelpers.Write(stream, ref arg2, s2, info2); - MySerializationHelpers.Write(stream, ref arg3, s3, info3); - MySerializationHelpers.Write(stream, ref arg4, s4, info4); - MySerializationHelpers.Write(stream, ref arg5, s5, info5); - } - } - - [Obsolete("The entire network intercept system is deprecated. Please use method patches instead.")] - public void Serialize(MethodInfo info, BitStream stream, ref T1 arg1, ref T2 arg2, ref T3 arg3, ref T4 arg4, ref T5 arg5, ref T6 arg6) - { - var s1 = MyFactory.GetSerializer(); - var s2 = MyFactory.GetSerializer(); - var s3 = MyFactory.GetSerializer(); - var s4 = MyFactory.GetSerializer(); - var s5 = MyFactory.GetSerializer(); - var s6 = MyFactory.GetSerializer(); - - var args = info.GetParameters(); - var info1 = MySerializeInfo.CreateForParameter(args, 0); - var info2 = MySerializeInfo.CreateForParameter(args, 1); - var info3 = MySerializeInfo.CreateForParameter(args, 2); - var info4 = MySerializeInfo.CreateForParameter(args, 3); - var info5 = MySerializeInfo.CreateForParameter(args, 4); - var info6 = MySerializeInfo.CreateForParameter(args, 5); - - if (stream.Reading) - { - MySerializationHelpers.CreateAndRead(stream, out arg1, s1, info1); - MySerializationHelpers.CreateAndRead(stream, out arg2, s2, info2); - MySerializationHelpers.CreateAndRead(stream, out arg3, s3, info3); - MySerializationHelpers.CreateAndRead(stream, out arg4, s4, info4); - MySerializationHelpers.CreateAndRead(stream, out arg5, s5, info5); - MySerializationHelpers.CreateAndRead(stream, out arg6, s6, info6); - } - else - { - MySerializationHelpers.Write(stream, ref arg1, s1, info1); - MySerializationHelpers.Write(stream, ref arg2, s2, info2); - MySerializationHelpers.Write(stream, ref arg3, s3, info3); - MySerializationHelpers.Write(stream, ref arg4, s4, info4); - MySerializationHelpers.Write(stream, ref arg5, s5, info5); - MySerializationHelpers.Write(stream, ref arg6, s6, info6); - } - } - - [Obsolete("The entire network intercept system is deprecated. Please use method patches instead.")] - public void Serialize(MethodInfo info, BitStream stream, ref T1 arg1, ref T2 arg2, ref T3 arg3, ref T4 arg4, ref T5 arg5, ref T6 arg6, ref T7 arg7) - { - var s1 = MyFactory.GetSerializer(); - var s2 = MyFactory.GetSerializer(); - var s3 = MyFactory.GetSerializer(); - var s4 = MyFactory.GetSerializer(); - var s5 = MyFactory.GetSerializer(); - var s6 = MyFactory.GetSerializer(); - var s7 = MyFactory.GetSerializer(); - - var args = info.GetParameters(); - var info1 = MySerializeInfo.CreateForParameter(args, 0); - var info2 = MySerializeInfo.CreateForParameter(args, 1); - var info3 = MySerializeInfo.CreateForParameter(args, 2); - var info4 = MySerializeInfo.CreateForParameter(args, 3); - var info5 = MySerializeInfo.CreateForParameter(args, 4); - var info6 = MySerializeInfo.CreateForParameter(args, 5); - var info7 = MySerializeInfo.CreateForParameter(args, 6); - - if ( stream.Reading ) - { - MySerializationHelpers.CreateAndRead(stream, out arg1, s1, info1); - MySerializationHelpers.CreateAndRead(stream, out arg2, s2, info2); - MySerializationHelpers.CreateAndRead(stream, out arg3, s3, info3); - MySerializationHelpers.CreateAndRead(stream, out arg4, s4, info4); - MySerializationHelpers.CreateAndRead(stream, out arg5, s5, info5); - MySerializationHelpers.CreateAndRead(stream, out arg6, s6, info6); - MySerializationHelpers.CreateAndRead(stream, out arg7, s7, info7); - } - else - { - MySerializationHelpers.Write(stream, ref arg1, s1, info1); - MySerializationHelpers.Write(stream, ref arg2, s2, info2); - MySerializationHelpers.Write(stream, ref arg3, s3, info3); - MySerializationHelpers.Write(stream, ref arg4, s4, info4); - MySerializationHelpers.Write(stream, ref arg5, s5, info5); - MySerializationHelpers.Write(stream, ref arg6, s6, info6); - MySerializationHelpers.Write(stream, ref arg7, s7, info7); - } - } - } -} diff --git a/Torch/Managers/NetworkManager/NetworkManager.cs b/Torch/Managers/NetworkManager/NetworkManager.cs index a054835..1bb9a95 100644 --- a/Torch/Managers/NetworkManager/NetworkManager.cs +++ b/Torch/Managers/NetworkManager/NetworkManager.cs @@ -10,16 +10,10 @@ using VRageMath; namespace Torch.Managers { - //TOOD: Make this not a manager, and instead just a static class? - public partial class NetworkManager : Manager, INetworkManager + public static class NetworkManager { private static Logger _log = LogManager.GetCurrentClassLogger(); - - public NetworkManager(ITorchBase torchInstance) : base(torchInstance) - { - - } - + #region Network Injection private static Dictionary _delegateCache = new Dictionary(); diff --git a/Torch/Managers/NetworkManager/NetworkManager_Deprecated.cs b/Torch/Managers/NetworkManager/NetworkManager_Deprecated.cs deleted file mode 100644 index 1c2c580..0000000 --- a/Torch/Managers/NetworkManager/NetworkManager_Deprecated.cs +++ /dev/null @@ -1,407 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Threading.Tasks; -using Sandbox.Engine.Multiplayer; -using Sandbox.Game.Multiplayer; -using Torch.API.Managers; -using Torch.Utils; -using VRage; -using VRage.Library.Collections; -using VRage.Network; -using VRageMath; - -namespace Torch.Managers -{ - //Everything in this file is deprecated and should be deleted Eventually(tm) - public partial class NetworkManager - { - [ReflectedGetter(Name = "m_methodInfoLookup")] - private static Func> _methodInfoLookupGetter; - private const int MAX_ARGUMENT = 6; - private const int GENERIC_PARAMETERS = 8; - private const int DISPATCH_PARAMETERS = 11; - private static readonly DBNull DbNull = DBNull.Value; - private static MethodInfo _dispatchInfo; - - private static MethodInfo DispatchEventInfo => _dispatchInfo ?? (_dispatchInfo = typeof(MyReplicationLayerBase).GetMethod("DispatchEvent", BindingFlags.NonPublic | BindingFlags.Instance)); - - private const string _myTransportLayerField = "TransportLayer"; - private const string _transportHandlersField = "m_handlers"; - private readonly HashSet _networkHandlers = new HashSet(); - private bool _init; - - [ReflectedGetter(Name = "m_typeTable")] - private static Func _typeTableGetter; - [ReflectedMethod(Type = typeof(MyReplicationLayer), Name = "GetObjectByNetworkId")] - private static Func _getObjectByNetworkId; - - private static bool ReflectionUnitTest(bool suppress = false) - { - try - { - var syncLayerType = typeof(MySyncLayer); - var transportLayerField = syncLayerType.GetField(_myTransportLayerField, BindingFlags.NonPublic | BindingFlags.Instance); - - if (transportLayerField == null) - throw new TypeLoadException("Could not find internal type for TransportLayer"); - - var transportLayerType = transportLayerField.FieldType; - - if (!Reflection.HasField(transportLayerType, _transportHandlersField)) - throw new TypeLoadException("Could not find Handlers field"); - - return true; - } - catch (TypeLoadException ex) - { - _log.Error(ex); - if (suppress) - return false; - throw; - } - } - - /// - public override void Attach() - { - //disable all this for now - _log.Warn("Network intercept disabled. Some plugins may not work correctly."); - return; - - if (_init) - return; - - _init = true; - - if (!ReflectionUnitTest()) - throw new InvalidOperationException("Reflection unit test failed."); - - //don't bother with nullchecks here, it was all handled in ReflectionUnitTest - var transportType = typeof(MySyncLayer).GetField(_myTransportLayerField, BindingFlags.NonPublic | BindingFlags.Instance).FieldType; - var transportInstance = typeof(MySyncLayer).GetField(_myTransportLayerField, BindingFlags.NonPublic | BindingFlags.Instance)?.GetValue(MyMultiplayer.Static.SyncLayer); - var handlers = (IDictionary)transportType.GetField(_transportHandlersField, BindingFlags.NonPublic | BindingFlags.Instance)?.GetValue(transportInstance); - var handlerTypeField = handlers.GetType().GenericTypeArguments[0].GetField("messageId"); //Should be MyTransportLayer.HandlerId - object id = null; - foreach (var key in handlers.Keys) - { - if ((MyMessageId)handlerTypeField.GetValue(key) != MyMessageId.RPC) - continue; - - id = key; - break; - } - if (id == null) - throw new InvalidOperationException("RPC handler not found."); - - //remove Keen's network listener - handlers.Remove(id); - //replace it with our own - handlers.Add(id, new Action(OnEvent)); - - //PrintDebug(); - - _log.Debug("Initialized network intercept"); - } - - /// - public override void Detach() - { - // TODO reverse what was done in Attach - } - - #region Network Injection - - - /// - /// Broadcasts an event to all connected clients - /// - /// - /// - /// - [Obsolete("Old injection system deprecated. Use the generic methods instead.")] - public void RaiseEvent(MethodInfo method, object obj, params object[] args) - { - //default(EndpointId) tells the network to broadcast the message - RaiseEvent(method, obj, default(EndpointId), args); - } - - /// - /// Sends an event to one client by SteamId - /// - /// - /// - /// - /// - [Obsolete("Old injection system deprecated. Use the generic methods instead.")] - public void RaiseEvent(MethodInfo method, object obj, ulong steamId, params object[] args) - { - RaiseEvent(method, obj, new EndpointId(steamId), args); - } - - /// - /// Sends an event to one client - /// - /// - /// - /// - /// - [Obsolete("Old injection system deprecated. Use the generic methods instead.")] - public void RaiseEvent(MethodInfo method, object obj, EndpointId endpoint, params object[] args) - { - if (method == null) - throw new ArgumentNullException(nameof(method), "MethodInfo cannot be null!"); - - if (args.Length > MAX_ARGUMENT) - throw new ArgumentOutOfRangeException(nameof(args), $"Cannot pass more than {MAX_ARGUMENT} arguments!"); - - var owner = obj as IMyEventOwner; - if (obj != null && owner == null) - throw new InvalidCastException("Provided event target is not of type IMyEventOwner!"); - - if (!method.HasAttribute()) - throw new CustomAttributeFormatException("Provided event target does not have the Event attribute! Replication will not succeed!"); - - //array to hold arguments to pass into DispatchEvent - object[] arguments = new object[DISPATCH_PARAMETERS]; - - - arguments[0] = obj == null ? TryGetStaticCallSite(method) : TryGetCallSite(method, obj); - arguments[1] = endpoint; - arguments[2] = new Vector3D?(); - arguments[3] = owner; - - //copy supplied arguments into the reflection arguments - for (var i = 0; i < args.Length; i++) - arguments[i + 4] = args[i]; - - //pad the array out with DBNull, skip last element - //last element should stay null (this is for blocking events -- not used?) - for (var j = args.Length + 4; j < arguments.Length - 1; j++) - arguments[j] = DbNull; - - //create an array of Types so we can create a generic method - var argTypes = new Type[GENERIC_PARAMETERS]; - - //any null arguments (not DBNull) must be of type IMyEventOwner - for (var k = 2; k < arguments.Length; k++) - argTypes[k - 2] = arguments[k]?.GetType() ?? typeof(IMyEventOwner); - - var parameters = method.GetParameters(); - for (var i = 0; i < parameters.Length; i++) - { - if (argTypes[i + 1] != parameters[i].ParameterType) - throw new TypeLoadException($"Type mismatch on method parameters. Expected {string.Join(", ", parameters.Select(p => p.ParameterType.ToString()))} got {string.Join(", ", argTypes.Select(t => t.ToString()))}"); - } - - //create a generic method of DispatchEvent and invoke to inject our data into the network - var dispatch = DispatchEventInfo.MakeGenericMethod(argTypes); - dispatch.Invoke(MyMultiplayer.ReplicationLayer, arguments); - } - - /// - /// Broadcasts a static event to all connected clients - /// - /// - /// - [Obsolete("Old injection system deprecated. Use the generic methods instead.")] - public void RaiseStaticEvent(MethodInfo method, params object[] args) - { - //default(EndpointId) tells the network to broadcast the message - RaiseStaticEvent(method, default(EndpointId), args); - } - - /// - /// Sends a static event to one client by SteamId - /// - /// - /// - /// - [Obsolete("Old injection system deprecated. Use the generic methods instead.")] - public void RaiseStaticEvent(MethodInfo method, ulong steamId, params object[] args) - { - RaiseEvent(method, (object)null, new EndpointId(steamId), args); - } - - /// - /// Sends a static event to one client - /// - /// - /// - /// - [Obsolete("Old injection system deprecated. Use the generic methods instead.")] - public void RaiseStaticEvent(MethodInfo method, EndpointId endpoint, params object[] args) - { - RaiseEvent(method, (object)null, endpoint, args); - } - - private CallSite TryGetStaticCallSite(MethodInfo method) - { - MyTypeTable typeTable = _typeTableGetter.Invoke(MyMultiplayer.ReplicationLayer); - if (!_methodInfoLookupGetter.Invoke(typeTable.StaticEventTable).TryGetValue(method, out CallSite result)) - throw new MissingMemberException("Provided event target not found!"); - return result; - } - - private CallSite TryGetCallSite(MethodInfo method, object arg) - { - MySynchronizedTypeInfo typeInfo = _typeTableGetter.Invoke(MyMultiplayer.ReplicationLayer).Get(arg.GetType()); - if (!_methodInfoLookupGetter.Invoke(typeInfo.EventTable).TryGetValue(method, out CallSite result)) - throw new MissingMemberException("Provided event target not found!"); - return result; - } - - #endregion - - #region Network Intercept - - [Obsolete] - //TODO: Change this to a method patch so I don't have to try to keep up with Keen. - /// - /// This is the main body of the network intercept system. When messages come in from clients, they are processed here - /// before being passed on to the game server. - /// - /// DO NOT modify this method unless you're absolutely sure of what you're doing. This can very easily destabilize the game! - /// - /// - private void OnEvent(MyPacket packet) - { - if (_networkHandlers.Count == 0) - { - //pass the message back to the game server - try - { - ((MyReplicationLayer)MyMultiplayer.ReplicationLayer).OnEvent(packet); - } - catch (Exception ex) - { - _log.Error(ex); - //crash after logging, bad things could happen if we continue on with bad data - throw; - } - return; - } - - var stream = new BitStream(); - stream.ResetRead(packet.BitStream); - - var networkId = stream.ReadNetworkId(); - //this value is unused, but removing this line corrupts the rest of the stream - var blockedNetworkId = stream.ReadNetworkId(); - var eventId = (uint)stream.ReadUInt16(); - bool flag = stream.ReadBool(); - Vector3D? position = new Vector3D?(); - if (flag) - position = new Vector3D?(stream.ReadVector3D()); - - CallSite site; - object obj; - if (networkId.IsInvalid) // Static event - { - site = _typeTableGetter.Invoke(MyMultiplayer.ReplicationLayer).StaticEventTable.Get(eventId); - obj = null; - } - else // Instance event - { - //var sendAs = ((MyReplicationLayer)MyMultiplayer.ReplicationLayer).GetObjectByNetworkId(networkId); - var sendAs = _getObjectByNetworkId((MyReplicationLayer)MyMultiplayer.ReplicationLayer, networkId); - if (sendAs == null) - { - return; - } - var typeInfo = _typeTableGetter.Invoke(MyMultiplayer.ReplicationLayer).Get(sendAs.GetType()); - var eventCount = typeInfo.EventTable.Count; - if (eventId < eventCount) // Directly - { - obj = sendAs; - site = typeInfo.EventTable.Get(eventId); - } - else // Through proxy - { - obj = ((IMyProxyTarget)sendAs).Target; - typeInfo = _typeTableGetter.Invoke(MyMultiplayer.ReplicationLayer).Get(obj.GetType()); - site = typeInfo.EventTable.Get(eventId - (uint)eventCount); // Subtract max id of Proxy - } - } - - //we're handling the network live in the game thread, this needs to go as fast as possible - var discard = false; - foreach (var handler in _networkHandlers) - //Parallel.ForEach(_networkHandlers, handler => - { - try - { - if (handler.CanHandle(site)) - discard |= handler.Handle(packet.Sender.Id.Value, site, stream, obj, packet); - } - catch (Exception ex) - { - //ApplicationLog.Error(ex.ToString()); - _log.Error(ex); - } - } - - //one of the handlers wants us to discard this packet - if (discard) - return; - - //pass the message back to the game server - try - { - ((MyReplicationLayer)MyMultiplayer.ReplicationLayer).OnEvent(packet); - } - catch (Exception ex) - { - _log.Error(ex, "Error processing network event!"); - _log.Error(ex); - //crash after logging, bad things could happen if we continue on with bad data - throw; - } - } - - [Obsolete("Deprecated. Use a method patch instead.")] - /// - public void RegisterNetworkHandler(INetworkHandler handler) - { - _log.Warn($"Plugin {handler.GetType().Assembly.FullName} registered a network handler. This system no longer works. Please alert the plugin author."); - return; - - var handlerType = handler.GetType().FullName; - var toRemove = new List(); - foreach (var item in _networkHandlers) - { - if (item.GetType().FullName == handlerType) - { - //if (ExtenderOptions.IsDebugging) - _log.Error("Network handler already registered! " + handlerType); - toRemove.Add(item); - } - } - - foreach (var oldHandler in toRemove) - _networkHandlers.Remove(oldHandler); - - _networkHandlers.Add(handler); - } - - [Obsolete("Deprecated. Use a method patch instead.")] - /// - public bool UnregisterNetworkHandler(INetworkHandler handler) - { - return _networkHandlers.Remove(handler); - } - - [Obsolete("Deprecated. Use a method patch instead.")] - public void RegisterNetworkHandlers(params INetworkHandler[] handlers) - { - foreach (var handler in handlers) - RegisterNetworkHandler(handler); - } - - #endregion - - } -} diff --git a/Torch/Managers/PatchManager/DecoratedMethod.cs b/Torch/Managers/PatchManager/DecoratedMethod.cs index 010a315..8c2e120 100644 --- a/Torch/Managers/PatchManager/DecoratedMethod.cs +++ b/Torch/Managers/PatchManager/DecoratedMethod.cs @@ -83,7 +83,7 @@ namespace Torch.Managers.PatchManager private DynamicMethod AllocatePatchMethod() { Debug.Assert(_method.DeclaringType != null); - var methodName = _method.Name + $"_{_patchSalt++}"; + var methodName = "Patched_" + _method.DeclaringType.FullName + _method.Name + $"_{_patchSalt++}"; var returnType = _method is MethodInfo meth ? meth.ReturnType : typeof(void); var parameters = _method.GetParameters(); var parameterTypes = (_method.IsStatic ? Enumerable.Empty() : new[] {typeof(object)}) diff --git a/Torch/Managers/ScriptingManager.cs b/Torch/Managers/ScriptingManager.cs deleted file mode 100644 index 11f73df..0000000 --- a/Torch/Managers/ScriptingManager.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Sandbox.ModAPI; -using Torch.API; -using Torch.API.Managers; -using Torch.API.ModAPI; -using Torch.API.ModAPI.Ingame; -using VRage.Scripting; - -namespace Torch.Managers -{ - public class ScriptingManager : IManager - { - private MyScriptWhitelist _whitelist; - - public void Attach() - { - _whitelist = MyScriptCompiler.Static.Whitelist; - MyScriptCompiler.Static.AddConditionalCompilationSymbols("TORCH"); - MyScriptCompiler.Static.AddReferencedAssemblies(typeof(ITorchBase).Assembly.Location); - MyScriptCompiler.Static.AddImplicitIngameNamespacesFromTypes(typeof(GridExtensions)); - - using (var whitelist = _whitelist.OpenBatch()) - { - whitelist.AllowNamespaceOfTypes(MyWhitelistTarget.ModApi, typeof(TorchAPI)); - whitelist.AllowNamespaceOfTypes(MyWhitelistTarget.Both, typeof(GridExtensions)); - } - - /* - //dump whitelist - var whitelist = new StringBuilder(); - foreach (var pair in MyScriptCompiler.Static.Whitelist.GetWhitelist()) - { - var split = pair.Key.Split(','); - whitelist.AppendLine("|-"); - whitelist.AppendLine($"|{pair.Value} || {split[0]} || {split[1]}"); - } - Log.Info(whitelist);*/ - } - - public void Detach() - { - // TODO unregister whitelist patches - } - - public void UnwhitelistType(Type t) - { - throw new NotImplementedException(); - } - } -} diff --git a/Torch/Managers/UpdateManager.cs b/Torch/Managers/UpdateManager.cs index 700de86..30ec6ce 100644 --- a/Torch/Managers/UpdateManager.cs +++ b/Torch/Managers/UpdateManager.cs @@ -44,7 +44,7 @@ namespace Torch.Managers private async void CheckAndUpdateTorch() { - if (!Torch.Config.GetTorchUpdates) + if (Torch.Config.NoUpdate || !Torch.Config.GetTorchUpdates) return; try diff --git a/Torch/Patches/GameAnalyticsPatch.cs b/Torch/Patches/GameAnalyticsPatch.cs index 66bcf72..2a38d91 100644 --- a/Torch/Patches/GameAnalyticsPatch.cs +++ b/Torch/Patches/GameAnalyticsPatch.cs @@ -12,7 +12,7 @@ namespace Torch.Patches public static class GameAnalyticsPatch { private static readonly Logger _log = LogManager.GetCurrentClassLogger(); - private static Action _setLogger; + private static Action _setLogger; public static void Patch(PatchContext ctx) { @@ -27,7 +27,7 @@ namespace Torch.Patches return; } RuntimeHelpers.RunClassConstructor(type.TypeHandle); - _setLogger = loggerField?.CreateSetter(); + _setLogger = loggerField?.CreateSetter(); FixLogging(); ConstructorInfo ctor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[0], new ParameterModifier[0]); @@ -42,7 +42,7 @@ namespace Torch.Patches private static void FixLogging() { - _setLogger(LogManager.GetLogger("GameAnalytics")); + _setLogger(null, LogManager.GetLogger("GameAnalytics")); if (!(LogManager.Configuration is XmlLoggingConfiguration)) LogManager.Configuration = new XmlLoggingConfiguration(Path.Combine( Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) ?? Environment.CurrentDirectory, "NLog.config")); diff --git a/Torch/Patches/GameStatePatchShim.cs b/Torch/Patches/GameStatePatchShim.cs index b2af4a7..f939189 100644 --- a/Torch/Patches/GameStatePatchShim.cs +++ b/Torch/Patches/GameStatePatchShim.cs @@ -19,7 +19,7 @@ namespace Torch.Patches internal static void Patch(PatchContext target) { - ConstructorInfo ctor = typeof(MySandboxGame).GetConstructor(new[] { typeof(string[]) }); + ConstructorInfo ctor = typeof(MySandboxGame).GetConstructor(new[] { typeof(string[]), typeof(IntPtr) }); if (ctor == null) throw new ArgumentException("Can't find constructor MySandboxGame(string[])"); target.GetPattern(ctor).Prefixes.Add(MethodRef(PrefixConstructor)); diff --git a/Torch/Patches/TorchAsyncSaving.cs b/Torch/Patches/TorchAsyncSaving.cs index 3c99e77..7c1eedc 100644 --- a/Torch/Patches/TorchAsyncSaving.cs +++ b/Torch/Patches/TorchAsyncSaving.cs @@ -67,6 +67,7 @@ namespace Torch.Patches if (!Game.IsDedicated && MySession.Static != null) ShowWorldSaveResult(tmpSnapshot.SavingSuccess); saveTaskSource.TrySetResult(tmpSnapshot.SavingSuccess ? GameSaveResult.Success : GameSaveResult.FailedToSaveToDisk); + return false; }); }); return saveTaskSource.Task; diff --git a/Torch/Torch.csproj b/Torch/Torch.csproj index ca60249..bf4beb9 100644 --- a/Torch/Torch.csproj +++ b/Torch/Torch.csproj @@ -212,7 +212,6 @@ - @@ -259,7 +258,6 @@ - @@ -279,7 +277,6 @@ - diff --git a/Torch/TorchBase.cs b/Torch/TorchBase.cs index 92f9964..063d34c 100644 --- a/Torch/TorchBase.cs +++ b/Torch/TorchBase.cs @@ -49,6 +49,7 @@ using VRage.Game.SessionComponents; using VRage.GameServices; using VRage.Library; using VRage.ObjectBuilders; +using VRage.Platform.Windows; using VRage.Plugins; using VRage.Scripting; using VRage.Steam; @@ -64,6 +65,7 @@ namespace Torch { static TorchBase() { + MyVRageWindows.Init("SpaceEngineersDedicated", MySandboxGame.Log, null, false); ReflectedManager.Process(typeof(TorchBase).Assembly); ReflectedManager.Process(typeof(ITorchBase).Assembly); PatchManager.AddPatchShim(typeof(GameStatePatchShim)); @@ -153,7 +155,6 @@ namespace Torch Plugins = new PluginManager(this); var sessionManager = new TorchSessionManager(this); - sessionManager.AddFactory((x) => MyMultiplayer.Static?.SyncLayer != null ? new NetworkManager(this) : null); sessionManager.AddFactory((x) => Sync.IsServer ? new ChatManagerServer(this) : new ChatManagerClient(this)); sessionManager.AddFactory((x) => Sync.IsServer ? new CommandManager(this) : null); sessionManager.AddFactory((x) => new EntityManager(this)); diff --git a/Torch/VRageGame.cs b/Torch/VRageGame.cs index 18d65fc..0f0530f 100644 --- a/Torch/VRageGame.cs +++ b/Torch/VRageGame.cs @@ -30,8 +30,6 @@ using VRage.Game; using VRage.Game.ObjectBuilder; using VRage.Game.SessionComponents; using VRage.GameServices; -using VRage.Network; -using VRage.Platform.Windows; using VRage.Plugins; using VRage.Steam; using VRage.Utils; @@ -157,8 +155,6 @@ namespace Torch _tweakGameSettings(); MyFileSystem.Reset(); - VRage.Platform.Windows.MyVRageWindows.Init(MySandboxGame.Log, Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "SpaceEngineersDedicated")); - MyVRageWindows.Init(MySandboxGame.Log, Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "SpaceEngineersDedicated")); MyInitializer.InvokeBeforeRun(_appSteamId, _appName, _userDataPath); // MyInitializer.InitCheckSum(); diff --git a/Torch/Views/PropertyGrid.xaml.cs b/Torch/Views/PropertyGrid.xaml.cs index b0e78b2..ede4714 100644 --- a/Torch/Views/PropertyGrid.xaml.cs +++ b/Torch/Views/PropertyGrid.xaml.cs @@ -221,7 +221,6 @@ namespace Torch.Views var gt = propertyType.GetGenericArguments()[0]; - //TODO: Is this the best option? Probably not if (gt.IsPrimitive || gt == typeof(string)) { button.Click += (sender, args) => EditPrimitiveCollection(((Button)sender).DataContext); From 036f21de81d98e3a2fecfeb5883e38924965b3cc Mon Sep 17 00:00:00 2001 From: John Gross Date: Thu, 22 Aug 2019 11:24:19 -0700 Subject: [PATCH 2/9] Fixy fix time, Keen touched the chat system --- Torch.Server/Initializer.cs | 2 +- Torch/Managers/ChatManager/ChatManagerClient.cs | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Torch.Server/Initializer.cs b/Torch.Server/Initializer.cs index 23d89e0..e152373 100644 --- a/Torch.Server/Initializer.cs +++ b/Torch.Server/Initializer.cs @@ -31,7 +31,7 @@ namespace Torch.Server private const string RUNSCRIPT = @"force_install_dir ../ login anonymous -app_update 298740 -beta publictest -betapassword nt8WuDw9kdvE validate +app_update 298740 quit"; private TorchConfig _config; diff --git a/Torch/Managers/ChatManager/ChatManagerClient.cs b/Torch/Managers/ChatManager/ChatManagerClient.cs index 5b0fbe4..ecdf1dc 100644 --- a/Torch/Managers/ChatManager/ChatManagerClient.cs +++ b/Torch/Managers/ChatManager/ChatManagerClient.cs @@ -15,6 +15,7 @@ using Torch.API; using Torch.API.Managers; using Torch.Utils; using VRage.Game; +using VRageMath; namespace Torch.Managers.ChatManager { @@ -82,7 +83,7 @@ namespace Torch.Managers.ChatManager _chatMessageRecievedReplacer.Replace(new Action(Multiplayer_ChatMessageReceived), MyMultiplayer.Static); _scriptedChatMessageRecievedReplacer.Replace( - new Action(Multiplayer_ScriptedChatMessageReceived), MyMultiplayer.Static); + new Action(Multiplayer_ScriptedChatMessageReceived), MyMultiplayer.Static); } else { @@ -141,7 +142,7 @@ namespace Torch.Managers.ChatManager _hudChatMessageReceived.Invoke(MyHud.Chat, steamUserId, messageText, channel, targetId, customAuthorName); } - private void Multiplayer_ScriptedChatMessageReceived(string message, string author, string font) + private void Multiplayer_ScriptedChatMessageReceived(string message, string author, string font, Color color) { var torchMsg = new TorchChatMessage(author, message, font); if (!RaiseMessageRecieved(torchMsg) && HasHud) From 28037e11dfbeb835cdc055a242fc608800b2f7fd Mon Sep 17 00:00:00 2001 From: John Gross Date: Thu, 22 Aug 2019 12:36:35 -0700 Subject: [PATCH 3/9] Fix more chat, add missing config UI --- .../ViewModels/SessionSettingsViewModel.cs | 33 +++++++++++++++++++ .../Managers/ChatManager/ChatManagerClient.cs | 4 +-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/Torch.Server/ViewModels/SessionSettingsViewModel.cs b/Torch.Server/ViewModels/SessionSettingsViewModel.cs index cdb4833..6037485 100644 --- a/Torch.Server/ViewModels/SessionSettingsViewModel.cs +++ b/Torch.Server/ViewModels/SessionSettingsViewModel.cs @@ -269,7 +269,40 @@ namespace Torch.Server.ViewModels [Torch.Views.Display(Description = "Enables automatic respawn at nearest available respawn point.", Name = "Enable Auto Respawn", GroupName = "Players")] public bool EnableAutoRespawn { get => _settings.EnableAutorespawn; set => SetValue(ref _settings.EnableAutorespawn, value); } + + [Torch.Views.Display(Description = "The number of NPC factions generated on the start of the world.", Name = "NPC Factions Count", GroupName = "NPCs")] + public int TradeFactionsCount { get => _settings.TradeFactionsCount; set => SetValue(ref _settings.TradeFactionsCount, value); } + + [Torch.Views.Display(Description = "The inner radius [m] (center is in 0,0,0), where stations can spawn. Does not affect planet-bound stations (surface Outposts and Orbital stations).", Name = "Stations Inner Radius", GroupName = "NPCs")] + public double StationsDistanceInnerRadius { get => _settings.StationsDistanceInnerRadius; set => SetValue(ref _settings.StationsDistanceInnerRadius, value); } + [Torch.Views.Display(Description = "The outer radius [m] (center is in 0,0,0), where stations can spawn. Does not affect planet-bound stations (surface Outposts and Orbital stations).", Name = "Stations Outer Radius Start", GroupName = "NPCs")] + public double StationsDistanceOuterRadiusStart { get => _settings.StationsDistanceOuterRadiusStart; set => SetValue(ref _settings.StationsDistanceOuterRadiusStart, value); } + + [Torch.Views.Display(Description = "The outer radius [m] (center is in 0,0,0), where stations can spawn. Does not affect planet-bound stations (surface Outposts and Orbital stations).", Name = "Stations Outer Radius End", GroupName = "NPCs")] + public double StationsDistanceOuterRadiusEnd { get => _settings.StationsDistanceOuterRadiusEnd; set => SetValue(ref _settings.StationsDistanceOuterRadiusEnd, value); } + + [Torch.Views.Display(Description = "Time period between two economy updates in seconds.", Name = "Economy tick time", GroupName = "NPCs")] + public int EconomyTickInSeconds { get => _settings.EconomyTickInSeconds; set => SetValue(ref _settings.EconomyTickInSeconds, value); } + + [Torch.Views.Display(Description = "If enabled bounty contracts will be available on stations.", Name = "Enable Bounty Contracts", GroupName = "Players")] + public bool EnableBountyContracts { get => _settings.EnableBountyContracts; set => SetValue(ref _settings.EnableBountyContracts, value); } + + [Torch.Views.Display(Description = "Resource deposits count coefficient for generated world content (voxel generator version > 2).", Name = "Deposits Count Coefficient", GroupName = "Environment")] + public float DepositsCountCoefficient { get => _settings.DepositsCountCoefficient; set => SetValue(ref _settings.DepositsCountCoefficient, value); } + + [Torch.Views.Display(Description = "Resource deposit size denominator for generated world content (voxel generator version > 2).", Name = "Deposit Size Denominator", GroupName = "Environment")] + public float DepositSideDenominator { get => _settings.DepositSizeDenominator; set => SetValue(ref _settings.DepositSizeDenominator, value); } + + [Torch.Views.Display(Description = "Enables economy features.", Name = "Enable Economy", GroupName = "NPCs")] + public bool EnableEconomy { get => _settings.EnableEconomy; set => SetValue(ref _settings.EnableEconomy, value); } + + [Torch.Views.Display(Description = "Enables system for voxel reverting.", Name = "Enable Voxel Reverting", GroupName = "Trash Removal")] + public bool VoxelTrashRemovalEnabled { get => _settings.VoxelTrashRemovalEnabled; set => SetValue(ref _settings.VoxelTrashRemovalEnabled, value); } + + [Torch.Views.Display(Description = "Allows super gridding exploit to be used.", Name = "Enable Supergridding", GroupName = "Others")] + public bool EnableSupergridding { get => _settings.EnableSupergridding; set => SetValue(ref _settings.EnableSupergridding, value); } + public SessionSettingsViewModel(MyObjectBuilder_SessionSettings settings) { _settings = settings; diff --git a/Torch/Managers/ChatManager/ChatManagerClient.cs b/Torch/Managers/ChatManager/ChatManagerClient.cs index ecdf1dc..94c6646 100644 --- a/Torch/Managers/ChatManager/ChatManagerClient.cs +++ b/Torch/Managers/ChatManager/ChatManagerClient.cs @@ -146,7 +146,7 @@ namespace Torch.Managers.ChatManager { var torchMsg = new TorchChatMessage(author, message, font); if (!RaiseMessageRecieved(torchMsg) && HasHud) - _hudChatScriptedMessageReceived.Invoke(MyHud.Chat, author, message, font); + _hudChatScriptedMessageReceived.Invoke(MyHud.Chat, author, message, font, color); } protected bool RaiseMessageRecieved(TorchChatMessage msg) @@ -164,7 +164,7 @@ namespace Torch.Managers.ChatManager [ReflectedMethod(Name = _hudChatMessageReceivedName)] private static Action _hudChatMessageReceived; [ReflectedMethod(Name = _hudChatScriptedMessageReceivedName)] - private static Action _hudChatScriptedMessageReceived; + private static Action _hudChatScriptedMessageReceived; [ReflectedEventReplace(typeof(MyMultiplayerBase), nameof(MyMultiplayerBase.ChatMessageReceived), typeof(MyHudChat), _hudChatMessageReceivedName)] private static Func _chatMessageReceivedFactory; From 1b4c5ace61b30f76b90f8f18fae5eed9e34e9c74 Mon Sep 17 00:00:00 2001 From: John Gross Date: Thu, 22 Aug 2019 15:46:40 -0700 Subject: [PATCH 4/9] Fix saving --- Torch/Patches/TorchAsyncSaving.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Torch/Patches/TorchAsyncSaving.cs b/Torch/Patches/TorchAsyncSaving.cs index 7c1eedc..4d4a23e 100644 --- a/Torch/Patches/TorchAsyncSaving.cs +++ b/Torch/Patches/TorchAsyncSaving.cs @@ -62,12 +62,11 @@ namespace Torch.Patches if (!Game.IsDedicated) TakeSaveScreenshot(); - tmpSnapshot.SaveParallel(() => + tmpSnapshot.SaveParallel(() => true, () => { if (!Game.IsDedicated && MySession.Static != null) ShowWorldSaveResult(tmpSnapshot.SavingSuccess); saveTaskSource.TrySetResult(tmpSnapshot.SavingSuccess ? GameSaveResult.Success : GameSaveResult.FailedToSaveToDisk); - return false; }); }); return saveTaskSource.Task; From 1e19f9aedf7a04a2a72c5144290fd91382df19e0 Mon Sep 17 00:00:00 2001 From: John Gross Date: Thu, 22 Aug 2019 20:38:35 -0700 Subject: [PATCH 5/9] Fix save tracking desync --- Torch/TorchBase.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Torch/TorchBase.cs b/Torch/TorchBase.cs index 063d34c..8128711 100644 --- a/Torch/TorchBase.cs +++ b/Torch/TorchBase.cs @@ -383,12 +383,14 @@ namespace Torch { if (exclusive) { - if (MyAsyncSaving.InProgress || Interlocked.Increment(ref _inProgressSaves) != 1) + if (MyAsyncSaving.InProgress || _inProgressSaves >= 0) { Log.Error("Failed to save game, game is already saving"); return null; } } + + Interlocked.Increment(ref _inProgressSaves); return TorchAsyncSaving.Save(this, timeoutMs).ContinueWith((task, torchO) => { var torch = (TorchBase) torchO; From 624bd5a2a49cfa3336f04158e10bfccc1dee5fce Mon Sep 17 00:00:00 2001 From: Brant Martin Date: Sun, 25 Aug 2019 11:03:24 -0400 Subject: [PATCH 6/9] Fix references --- Torch/Torch.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Torch/Torch.csproj b/Torch/Torch.csproj index bf4beb9..abab057 100644 --- a/Torch/Torch.csproj +++ b/Torch/Torch.csproj @@ -169,7 +169,7 @@ False - ..\bin\x64\Release\DedicatedServer64\VRage.Platform.Windows.dll + ..\GameBinaries\VRage.Platform.Windows.dll ..\GameBinaries\VRage.Render.dll From 7bfc6077b92193ac9f52c015f3462340fa411e0c Mon Sep 17 00:00:00 2001 From: Brant Martin Date: Sun, 25 Aug 2019 11:04:08 -0400 Subject: [PATCH 7/9] Set game thread locale to English. Should give English exceptions now. --- Torch/TorchBase.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Torch/TorchBase.cs b/Torch/TorchBase.cs index 8128711..b8d0c30 100644 --- a/Torch/TorchBase.cs +++ b/Torch/TorchBase.cs @@ -414,6 +414,7 @@ namespace Torch Game.SignalStart(); if (!Game.WaitFor(VRageGame.GameState.Running)) Log.Warn("Failed to wait for the game to be started"); + Invoke(() => Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US")); } /// From ef444730b756d38e43a04fbd80fbbfcce86e3bed Mon Sep 17 00:00:00 2001 From: Brant Martin Date: Sun, 25 Aug 2019 11:20:35 -0400 Subject: [PATCH 8/9] Fix dumb arithmetic error breaking saves. Closes #336 --- Torch/TorchBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Torch/TorchBase.cs b/Torch/TorchBase.cs index b8d0c30..edf8277 100644 --- a/Torch/TorchBase.cs +++ b/Torch/TorchBase.cs @@ -383,7 +383,7 @@ namespace Torch { if (exclusive) { - if (MyAsyncSaving.InProgress || _inProgressSaves >= 0) + if (MyAsyncSaving.InProgress || _inProgressSaves > 0) { Log.Error("Failed to save game, game is already saving"); return null; From 997a3ca31c5a2bc91d2998ed275d8d2015d836a1 Mon Sep 17 00:00:00 2001 From: Brant Martin Date: Sun, 25 Aug 2019 11:55:14 -0400 Subject: [PATCH 9/9] Adjust behavior of restarts. Closes #337 --- Torch.API/ITorchBase.cs | 2 +- Torch.Server/TorchServer.cs | 5 +++-- Torch/Commands/TorchCommands.cs | 16 +++++++++++----- Torch/TorchBase.cs | 2 +- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/Torch.API/ITorchBase.cs b/Torch.API/ITorchBase.cs index 779d004..9b1a335 100644 --- a/Torch.API/ITorchBase.cs +++ b/Torch.API/ITorchBase.cs @@ -104,7 +104,7 @@ namespace Torch.API /// /// Restart the Torch instance, blocking until the restart has been performed. /// - void Restart(); + void Restart(bool save = true); /// /// Initializes a save of the game. diff --git a/Torch.Server/TorchServer.cs b/Torch.Server/TorchServer.cs index 0f593f3..503a277 100644 --- a/Torch.Server/TorchServer.cs +++ b/Torch.Server/TorchServer.cs @@ -152,14 +152,15 @@ namespace Torch.Server /// /// Restart the program. /// - public override void Restart() + public override void Restart(bool save = true) { if (Config.DisconnectOnRestart) { ModCommunication.SendMessageToClients(new JoinServerMessage("0.0.0.0:25555")); + Log.Info("Ejected all players from server for restart."); } - if (IsRunning) + if (IsRunning && save) Save().ContinueWith(DoRestart, this, TaskContinuationOptions.RunContinuationsAsynchronously); else DoRestart(null, this); diff --git a/Torch/Commands/TorchCommands.cs b/Torch/Commands/TorchCommands.cs index accb888..05c6867 100644 --- a/Torch/Commands/TorchCommands.cs +++ b/Torch/Commands/TorchCommands.cs @@ -8,6 +8,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using System.Timers; +using NLog; using Sandbox.Game.Multiplayer; using Sandbox.ModAPI; using Steamworks; @@ -28,6 +29,7 @@ namespace Torch.Commands { private static bool _restartPending = false; private static bool _cancelRestart = false; + private static readonly Logger Log = LogManager.GetCurrentClassLogger(); [Command("whatsmyip")] [Permission(MyPromoteLevel.None)] @@ -176,6 +178,7 @@ namespace Torch.Commands } _restartPending = true; + Task.Run(() => { var countdown = RestartCountdown(countdownSeconds, save).GetEnumerator(); @@ -232,15 +235,18 @@ namespace Torch.Commands else { if (save) - Context.Torch.Save().ContinueWith(x => Restart()); - else - Restart(); + { + Log.Info("Savin game before restart."); + Context.Torch.CurrentSession.Managers.GetManager() + .SendMessageAsSelf($"Saving game before restart."); + } + + Log.Info("Restarting server."); + Context.Torch.Invoke(() => Context.Torch.Restart(save)); yield break; } } - - void Restart() => Context.Torch.Invoke(() => Context.Torch.Restart()); } private string Pluralize(int num) diff --git a/Torch/TorchBase.cs b/Torch/TorchBase.cs index edf8277..8ad7f16 100644 --- a/Torch/TorchBase.cs +++ b/Torch/TorchBase.cs @@ -427,7 +427,7 @@ namespace Torch } /// - public abstract void Restart(); + public abstract void Restart(bool save = true); /// public virtual void Init(object gameInstance)