diff --git a/Torch.API/ITorchBase.cs b/Torch.API/ITorchBase.cs
index 6c851ab..c319818 100644
--- a/Torch.API/ITorchBase.cs
+++ b/Torch.API/ITorchBase.cs
@@ -103,6 +103,16 @@ namespace Torch.API
/// Initialize the Torch instance.
///
void Init();
+
+ ///
+ /// The current state of the game this instance of torch is controlling.
+ ///
+ TorchGameState GameState { get; }
+
+ ///
+ /// Event raised when changes.
+ ///
+ event TorchGameStateChangedDel GameStateChanged;
}
///
@@ -121,6 +131,6 @@ namespace Torch.API
///
public interface ITorchClient : ITorchBase
{
-
+
}
}
diff --git a/Torch.API/Torch.API.csproj b/Torch.API/Torch.API.csproj
index d771abd..bbf2e3b 100644
--- a/Torch.API/Torch.API.csproj
+++ b/Torch.API/Torch.API.csproj
@@ -186,6 +186,7 @@
+
diff --git a/Torch.API/TorchGameState.cs b/Torch.API/TorchGameState.cs
new file mode 100644
index 0000000..5c81393
--- /dev/null
+++ b/Torch.API/TorchGameState.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Sandbox;
+
+namespace Torch.API
+{
+ ///
+ /// Represents the state of a
+ ///
+ public enum TorchGameState
+ {
+ ///
+ /// The game is currently being created.
+ ///
+ Creating,
+ ///
+ /// The game has been created and is ready to begin loading.
+ ///
+ Created,
+ ///
+ /// The game is currently loading.
+ ///
+ Loading,
+ ///
+ /// The game is fully loaded and ready to start sessions
+ ///
+ Loaded,
+ ///
+ /// The game is beginning the unload sequence
+ ///
+ Unloading,
+ ///
+ /// The game has been shutdown and is no longer active
+ ///
+ Unloaded
+ }
+
+ ///
+ /// Callback raised when a game's state changes
+ ///
+ /// The game who had a state change
+ /// The game's new state
+ public delegate void TorchGameStateChangedDel(MySandboxGame game, TorchGameState newState);
+}
diff --git a/Torch.Server/TorchServer.cs b/Torch.Server/TorchServer.cs
index b5dfef4..afd6bfe 100644
--- a/Torch.Server/TorchServer.cs
+++ b/Torch.Server/TorchServer.cs
@@ -95,7 +95,6 @@ namespace Torch.Server
MyGlobalTypeMetadata.Static.Init();
GetManager().LoadInstance(Config.InstancePath);
- Plugins.LoadPlugins();
}
private void InvokeBeforeRun()
diff --git a/Torch/Managers/PatchManager/MSIL/ITokenResolver.cs b/Torch/Managers/PatchManager/MSIL/ITokenResolver.cs
index ffaac0a..5b85c93 100644
--- a/Torch/Managers/PatchManager/MSIL/ITokenResolver.cs
+++ b/Torch/Managers/PatchManager/MSIL/ITokenResolver.cs
@@ -24,7 +24,7 @@ namespace Torch.Managers.PatchManager.MSIL
{
_module = method.Module;
_genericTypeArgs = method.DeclaringType?.GenericTypeArguments ?? new Type[0];
- _genericMethArgs = method.GetGenericArguments();
+ _genericMethArgs = (method is MethodInfo ? method.GetGenericArguments() : new Type[0]);
}
public MemberInfo ResolveMember(int token)
diff --git a/Torch/Managers/PluginManager.cs b/Torch/Managers/PluginManager.cs
index c6828e2..92112f2 100644
--- a/Torch/Managers/PluginManager.cs
+++ b/Torch/Managers/PluginManager.cs
@@ -148,7 +148,7 @@ namespace Torch.Managers
var dlls = Directory.GetFiles(PluginDir, "*.dll", SearchOption.AllDirectories);
foreach (var dllPath in dlls)
{
- _log.Debug($"Loading plugin {dllPath}");
+ _log.Info($"Loading plugin {dllPath}");
var asm = Assembly.UnsafeLoadFrom(dllPath);
foreach (var type in asm.GetExportedTypes())
diff --git a/Torch/TorchBase.cs b/Torch/TorchBase.cs
index 00cccaa..7bf0b18 100644
--- a/Torch/TorchBase.cs
+++ b/Torch/TorchBase.cs
@@ -120,12 +120,13 @@ namespace Torch
sessionManager.AddFactory((x) => new EntityManager(this));
Managers.AddManager(sessionManager);
- Managers.AddManager(new PatchManager(this));
- Managers.AddManager(new KeenLogManager(this));
+ var patcher = new PatchManager(this);
+ GameStateInjector.Inject(patcher.AcquireContext());
+ Managers.AddManager(patcher);
+ // Managers.AddManager(new KeenLogManager(this));
Managers.AddManager(new FilesystemManager(this));
Managers.AddManager(new UpdateManager(this));
Managers.AddManager(Plugins);
-
TorchAPI.Instance = this;
}
@@ -269,6 +270,7 @@ namespace Torch
MySession.OnUnloading += OnSessionUnloading;
MySession.OnUnloaded += OnSessionUnloaded;
RegisterVRagePlugin();
+ Managers.GetManager().LoadPlugins();
Managers.Attach();
_init = true;
}
@@ -383,5 +385,90 @@ namespace Torch
{
GetManager().UpdatePlugins();
}
+
+
+ private TorchGameState _gameState = TorchGameState.Unloaded;
+
+ ///
+ public TorchGameState GameState
+ {
+ get => _gameState;
+ private set
+ {
+ _gameState = value;
+ GameStateChanged?.Invoke(MySandboxGame.Static, _gameState);
+ Log.Info($"Game state changed {_gameState}");
+ }
+ }
+
+ ///
+ public event TorchGameStateChangedDel GameStateChanged;
+
+ #region GameStateInjecting
+ private static class GameStateInjector
+ {
+#pragma warning disable 649
+ [ReflectedMethodInfo(typeof(MySandboxGame), nameof(MySandboxGame.Dispose))]
+ private static MethodInfo _sandboxGameDispose;
+ [ReflectedMethodInfo(typeof(MySandboxGame), "Initialize")]
+ private static MethodInfo _sandboxGameInit;
+#pragma warning restore 649
+
+ internal static void Inject(PatchContext target)
+ {
+ ConstructorInfo ctor = typeof(MySandboxGame).GetConstructor(new[] {typeof(string[])});
+ if (ctor == null)
+ throw new ArgumentException("Can't find constructor MySandboxGame(string[])");
+ target.GetPattern(ctor).Prefixes.Add(MethodRef(nameof(PrefixConstructor)));
+ target.GetPattern(ctor).Suffixes.Add(MethodRef(nameof(SuffixConstructor)));
+ target.GetPattern(_sandboxGameInit).Prefixes.Add(MethodRef(nameof(PrefixInit)));
+ target.GetPattern(_sandboxGameInit).Suffixes.Add(MethodRef(nameof(SuffixInit)));
+ target.GetPattern(_sandboxGameDispose).Prefixes.Add(MethodRef(nameof(PrefixDispose)));
+ target.GetPattern(_sandboxGameDispose).Suffixes.Add(MethodRef(nameof(SuffixDispose)));
+ }
+
+ private static MethodInfo MethodRef(string name)
+ {
+ return typeof(GameStateInjector).GetMethod(name,
+ BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
+ }
+
+ private static void PrefixConstructor()
+ {
+ if (Instance is TorchBase tb)
+ tb.GameState = TorchGameState.Creating;
+ }
+
+ private static void SuffixConstructor()
+ {
+ if (Instance is TorchBase tb)
+ tb.GameState = TorchGameState.Created;
+ }
+
+ private static void PrefixInit()
+ {
+ if (Instance is TorchBase tb)
+ tb.GameState = TorchGameState.Loading;
+ }
+
+ private static void SuffixInit()
+ {
+ if (Instance is TorchBase tb)
+ tb.GameState = TorchGameState.Loaded;
+ }
+
+ private static void PrefixDispose()
+ {
+ if (Instance is TorchBase tb)
+ tb.GameState = TorchGameState.Unloading;
+ }
+
+ private static void SuffixDispose()
+ {
+ if (Instance is TorchBase tb)
+ tb.GameState = TorchGameState.Unloaded;
+ }
+ }
+ #endregion
}
}
diff --git a/Torch/Utils/TorchAssemblyResolver.cs b/Torch/Utils/TorchAssemblyResolver.cs
index ca1f6bb..7b558bd 100644
--- a/Torch/Utils/TorchAssemblyResolver.cs
+++ b/Torch/Utils/TorchAssemblyResolver.cs
@@ -67,7 +67,7 @@ namespace Torch.Utils
string assemblyPath = Path.Combine(path, assemblyName + ".dll");
if (!File.Exists(assemblyPath))
continue;
- _log.Debug("Loading {0} from {1}", assemblyName, SimplifyPath(assemblyPath));
+ _log.Trace("Loading {0} from {1}", assemblyName, SimplifyPath(assemblyPath));
LogManager.Flush();
Assembly asm = Assembly.LoadFrom(assemblyPath);
_assemblies.Add(assemblyName, asm);