Merge pull request #81 from TorchAPI/sessions-manager-71

Session Management System
This commit is contained in:
John Gross
2017-08-22 11:09:04 -04:00
committed by GitHub
10 changed files with 257 additions and 6 deletions

View File

@@ -4,6 +4,7 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Torch.API.Managers; using Torch.API.Managers;
using Torch.API.Session;
using VRage.Game.ModAPI; using VRage.Game.ModAPI;
namespace Torch.API namespace Torch.API
@@ -33,15 +34,22 @@ namespace Torch.API
/// </summary> /// </summary>
event Action SessionUnloaded; event Action SessionUnloaded;
/// <summary>
/// Gets the currently running session instance, or null if none exists.
/// </summary>
ITorchSession CurrentSession { get; }
/// <summary> /// <summary>
/// Configuration for the current instance. /// Configuration for the current instance.
/// </summary> /// </summary>
ITorchConfig Config { get; } ITorchConfig Config { get; }
/// <inheritdoc cref="IMultiplayerManager"/> /// <inheritdoc cref="IMultiplayerManager"/>
[Obsolete]
IMultiplayerManager Multiplayer { get; } IMultiplayerManager Multiplayer { get; }
/// <inheritdoc cref="IPluginManager"/> /// <inheritdoc cref="IPluginManager"/>
[Obsolete]
IPluginManager Plugins { get; } IPluginManager Plugins { get; }
/// <inheritdoc cref="IDependencyManager"/> /// <inheritdoc cref="IDependencyManager"/>

View File

@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Sandbox.Game.World;
using Torch.API.Managers;
namespace Torch.API.Session
{
/// <summary>
/// Represents the Torch code working with a single game session
/// </summary>
public interface ITorchSession
{
/// <summary>
/// The Torch instance this session is bound to
/// </summary>
ITorchBase Torch { get; }
/// <summary>
/// The Space Engineers game session this session is bound to.
/// </summary>
MySession KeenSession { get; }
/// <inheritdoc cref="IDependencyManager"/>
IDependencyManager Managers { get; }
}
}

View File

@@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Torch.API.Managers;
namespace Torch.API.Session
{
/// <summary>
/// Creates a manager for the given session if applicable.
/// </summary>
/// <remarks>
/// This is for creating managers that will live inside the session, not the manager that controls sesssions.
/// </remarks>
/// <param name="session">The session to construct a bound manager for</param>
/// <returns>The manager that will live in the session, or null if none.</returns>
public delegate IManager SessionManagerFactoryDel(ITorchSession session);
/// <summary>
/// Manages the creation and destruction of <see cref="ITorchSession"/> instances for each <see cref="Sandbox.Game.World.MySession"/> created by Space Engineers.
/// </summary>
public interface ITorchSessionManager : IManager
{
/// <summary>
/// The currently running session
/// </summary>
ITorchSession CurrentSession { get; }
/// <summary>
/// Adds the given factory as a supplier for session based managers
/// </summary>
/// <param name="factory">Session based manager supplier</param>
/// <returns>true if added, false if already present</returns>
/// <exception cref="ArgumentNullException">If the factory is null</exception>
bool AddFactory(SessionManagerFactoryDel factory);
/// <summary>
/// Remove the given factory from the suppliers for session based managers
/// </summary>
/// <param name="factory">Session based manager supplier</param>
/// <returns>true if removed, false if not present</returns>
/// <exception cref="ArgumentNullException">If the factory is null</exception>
bool RemoveFactory(SessionManagerFactoryDel factory);
}
}

View File

@@ -175,6 +175,8 @@
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ServerState.cs" /> <Compile Include="ServerState.cs" />
<Compile Include="ModAPI\TorchAPI.cs" /> <Compile Include="ModAPI\TorchAPI.cs" />
<Compile Include="Session\ITorchSession.cs" />
<Compile Include="Session\ITorchSessionManager.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="packages.config" /> <None Include="packages.config" />

View File

@@ -12,6 +12,7 @@ using VRage.Steam;
using Torch.API; using Torch.API;
using VRage; using VRage;
using VRage.FileSystem; using VRage.FileSystem;
using VRage.GameServices;
using VRageRender; using VRageRender;
using VRageRender.ExternalApp; using VRageRender.ExternalApp;
@@ -53,7 +54,7 @@ namespace Torch.Client
_startup.DetectSharpDxLeaksBeforeRun(); _startup.DetectSharpDxLeaksBeforeRun();
var steamService = new SteamService(Game.IsDedicated, APP_ID); var steamService = new SteamService(Game.IsDedicated, APP_ID);
MyServiceManager.Instance.AddService(steamService); MyServiceManager.Instance.AddService<IMyGameService>(steamService);
_renderer = null; _renderer = null;
SpaceEngineersGame.SetupPerGameSettings(); SpaceEngineersGame.SetupPerGameSettings();
// I'm sorry, but it's what Keen does in SpaceEngineers.MyProgram // I'm sorry, but it's what Keen does in SpaceEngineers.MyProgram

View File

@@ -0,0 +1,49 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NLog;
using Sandbox.Game.World;
using Torch.API;
using Torch.API.Managers;
using Torch.API.Session;
using Torch.Managers;
namespace Torch.Session
{
public class TorchSession : ITorchSession
{
private static readonly Logger _log = LogManager.GetCurrentClassLogger();
/// <summary>
/// The Torch instance this session is bound to
/// </summary>
public ITorchBase Torch { get; }
/// <summary>
/// The Space Engineers game session this session is bound to.
/// </summary>
public MySession KeenSession { get; }
/// <inheritdoc cref="IDependencyManager"/>
public IDependencyManager Managers { get; }
public TorchSession(ITorchBase torch, MySession keenSession)
{
Torch = torch;
KeenSession = keenSession;
Managers = new DependencyManager(torch.Managers);
}
internal void Attach()
{
Managers.Attach();
}
internal void Detach()
{
Managers.Detach();
}
}
}

View File

@@ -0,0 +1,93 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NLog;
using Sandbox.Game.World;
using Torch.API;
using Torch.API.Managers;
using Torch.API.Session;
using Torch.Managers;
using Torch.Session;
namespace Torch.Session
{
/// <summary>
/// Manages the creation and destruction of <see cref="TorchSession"/> instances for each <see cref="MySession"/> created by Space Engineers.
/// </summary>
public class TorchSessionManager : Manager, ITorchSessionManager
{
private static readonly Logger _log = LogManager.GetCurrentClassLogger();
private TorchSession _currentSession;
/// <inheritdoc/>
public ITorchSession CurrentSession => _currentSession;
private readonly HashSet<SessionManagerFactoryDel> _factories = new HashSet<SessionManagerFactoryDel>();
public TorchSessionManager(ITorchBase torchInstance) : base(torchInstance)
{
}
/// <inheritdoc/>
public bool AddFactory(SessionManagerFactoryDel factory)
{
if (factory == null)
throw new ArgumentNullException(nameof(factory), "Factory must be non-null");
return _factories.Add(factory);
}
/// <inheritdoc/>
public bool RemoveFactory(SessionManagerFactoryDel factory)
{
if (factory == null)
throw new ArgumentNullException(nameof(factory), "Factory must be non-null");
return _factories.Remove(factory);
}
private void SessionLoaded()
{
if (_currentSession != null)
{
_log.Warn($"Override old torch session {_currentSession.KeenSession.Name}");
_currentSession.Detach();
}
_log.Info($"Starting new torch session for {MySession.Static.Name}");
_currentSession = new TorchSession(Torch, MySession.Static);
foreach (SessionManagerFactoryDel factory in _factories)
{
IManager manager = factory(CurrentSession);
if (manager != null)
CurrentSession.Managers.AddManager(manager);
}
(CurrentSession as TorchSession)?.Attach();
}
private void SessionUnloaded()
{
if (_currentSession == null)
return;
_log.Info($"Unloading torch session for {_currentSession.KeenSession.Name}");
_currentSession.Detach();
_currentSession = null;
}
/// <inheritdoc/>
public override void Attach()
{
MySession.AfterLoading += SessionLoaded;
MySession.OnUnloaded += SessionUnloaded;
}
/// <inheritdoc/>
public override void Detach()
{
_currentSession?.Detach();
_currentSession = null;
MySession.AfterLoading -= SessionLoaded;
MySession.OnUnloaded -= SessionUnloaded;
}
}
}

View File

@@ -3,9 +3,11 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using NLog;
using SteamSDK; using SteamSDK;
using VRage.Steam; using VRage.Steam;
using Sandbox; using Sandbox;
using Sandbox.Engine.Networking;
using Torch.Utils; using Torch.Utils;
using VRage.GameServices; using VRage.GameServices;
@@ -19,6 +21,9 @@ namespace Torch
/// </summary> /// </summary>
public class SteamService : MySteamService public class SteamService : MySteamService
{ {
private static readonly Logger _log = LogManager.GetCurrentClassLogger();
#pragma warning disable 649
[ReflectedSetter(Name = nameof(SteamServerAPI))] [ReflectedSetter(Name = nameof(SteamServerAPI))]
private static Action<MySteamService, SteamServerAPI> _steamServerAPISetter; private static Action<MySteamService, SteamServerAPI> _steamServerAPISetter;
[ReflectedSetter(Name = "m_gameServer")] [ReflectedSetter(Name = "m_gameServer")]
@@ -45,6 +50,7 @@ namespace Torch
private static Action<MySteamService> RegisterCallbacks; private static Action<MySteamService> RegisterCallbacks;
[ReflectedSetter(Name = nameof(Peer2Peer))] [ReflectedSetter(Name = nameof(Peer2Peer))]
private static Action<MySteamService, IMyPeer2Peer> _steamPeer2PeerSetter; private static Action<MySteamService, IMyPeer2Peer> _steamPeer2PeerSetter;
#pragma warning restore 649
public SteamService(bool isDedicated, uint appId) public SteamService(bool isDedicated, uint appId)
: base(true, appId) : base(true, appId)
@@ -63,7 +69,10 @@ namespace Torch
{ {
SteamAPI steamApi = SteamAPI.Instance; SteamAPI steamApi = SteamAPI.Instance;
_steamApiSetter.Invoke(this, steamApi); _steamApiSetter.Invoke(this, steamApi);
_steamIsActiveSetter.Invoke(this, steamApi.Init()); bool initResult = steamApi.Init();
if (!initResult)
_log.Warn("Failed to initialize SteamService");
_steamIsActiveSetter.Invoke(this, initResult);
if (IsActive) if (IsActive)
{ {
@@ -76,7 +85,8 @@ namespace Torch
_steamInventoryAPISetter.Invoke(this, new MySteamInventory()); _steamInventoryAPISetter.Invoke(this, new MySteamInventory());
RegisterCallbacks(this); RegisterCallbacks(this);
} } else
_log.Warn("SteamService isn't initialized; Torch Client won't start");
} }
_steamPeer2PeerSetter.Invoke(this, new MySteamPeer2Peer()); _steamPeer2PeerSetter.Invoke(this, new MySteamPeer2Peer());

View File

@@ -151,7 +151,6 @@
<Compile Include="Collections\ObservableList.cs" /> <Compile Include="Collections\ObservableList.cs" />
<Compile Include="DispatcherExtensions.cs" /> <Compile Include="DispatcherExtensions.cs" />
<Compile Include="Managers\DependencyManager.cs" /> <Compile Include="Managers\DependencyManager.cs" />
<Compile Include="Utils\ReflectedManager.cs" />
<Compile Include="SaveGameStatus.cs" /> <Compile Include="SaveGameStatus.cs" />
<Compile Include="Collections\KeyTree.cs" /> <Compile Include="Collections\KeyTree.cs" />
<Compile Include="Collections\ObservableDictionary.cs" /> <Compile Include="Collections\ObservableDictionary.cs" />
@@ -180,9 +179,12 @@
<Compile Include="Utils\Reflection.cs" /> <Compile Include="Utils\Reflection.cs" />
<Compile Include="Managers\ScriptingManager.cs" /> <Compile Include="Managers\ScriptingManager.cs" />
<Compile Include="Utils\TorchAssemblyResolver.cs" /> <Compile Include="Utils\TorchAssemblyResolver.cs" />
<Compile Include="Utils\ReflectedManager.cs" />
<Compile Include="Session\TorchSessionManager.cs" />
<Compile Include="TorchBase.cs" /> <Compile Include="TorchBase.cs" />
<Compile Include="SteamService.cs" /> <Compile Include="SteamService.cs" />
<Compile Include="TorchPluginBase.cs" /> <Compile Include="TorchPluginBase.cs" />
<Compile Include="Session\TorchSession.cs" />
<Compile Include="ViewModels\ModViewModel.cs" /> <Compile Include="ViewModels\ModViewModel.cs" />
<Compile Include="Collections\MTObservableCollection.cs" /> <Compile Include="Collections\MTObservableCollection.cs" />
<Compile Include="Extensions\MyPlayerCollectionExtensions.cs" /> <Compile Include="Extensions\MyPlayerCollectionExtensions.cs" />

View File

@@ -19,9 +19,11 @@ using SpaceEngineers.Game;
using Torch.API; using Torch.API;
using Torch.API.Managers; using Torch.API.Managers;
using Torch.API.ModAPI; using Torch.API.ModAPI;
using Torch.API.Session;
using Torch.Commands; using Torch.Commands;
using Torch.Managers; using Torch.Managers;
using Torch.Utils; using Torch.Utils;
using Torch.Session;
using VRage.Collections; using VRage.Collections;
using VRage.FileSystem; using VRage.FileSystem;
using VRage.Game.ObjectBuilder; using VRage.Game.ObjectBuilder;
@@ -57,15 +59,24 @@ namespace Torch
/// <inheritdoc /> /// <inheritdoc />
public string[] RunArgs { get; set; } public string[] RunArgs { get; set; }
/// <inheritdoc /> /// <inheritdoc />
[Obsolete]
public IPluginManager Plugins { get; protected set; } public IPluginManager Plugins { get; protected set; }
/// <inheritdoc /> /// <inheritdoc />
[Obsolete]
public IMultiplayerManager Multiplayer { get; protected set; } public IMultiplayerManager Multiplayer { get; protected set; }
/// <inheritdoc /> /// <inheritdoc />
[Obsolete]
public EntityManager Entities { get; protected set; } public EntityManager Entities { get; protected set; }
/// <inheritdoc /> /// <inheritdoc />
[Obsolete]
public INetworkManager Network { get; protected set; } public INetworkManager Network { get; protected set; }
/// <inheritdoc /> /// <inheritdoc />
[Obsolete]
public CommandManager Commands { get; protected set; } public CommandManager Commands { get; protected set; }
/// <inheritdoc />
public ITorchSession CurrentSession => Managers?.GetManager<ITorchSessionManager>()?.CurrentSession;
/// <inheritdoc /> /// <inheritdoc />
public event Action SessionLoading; public event Action SessionLoading;
/// <inheritdoc /> /// <inheritdoc />
@@ -107,6 +118,7 @@ namespace Torch
Network = new NetworkManager(this); Network = new NetworkManager(this);
Commands = new CommandManager(this); Commands = new CommandManager(this);
Managers.AddManager(new TorchSessionManager(this));
Managers.AddManager(new FilesystemManager(this)); Managers.AddManager(new FilesystemManager(this));
Managers.AddManager(new UpdateManager(this)); Managers.AddManager(new UpdateManager(this));
Managers.AddManager(Network); Managers.AddManager(Network);
@@ -116,7 +128,6 @@ namespace Torch
Managers.AddManager(Entities); Managers.AddManager(Entities);
Managers.AddManager(new ChatManager(this)); Managers.AddManager(new ChatManager(this));
TorchAPI.Instance = this; TorchAPI.Instance = this;
} }