Files
Torch/Torch/TorchBase.cs
2017-01-03 23:09:09 -08:00

126 lines
3.6 KiB
C#

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using NLog;
using Sandbox;
using Torch.API;
using VRage.Scripting;
namespace Torch
{
public abstract class TorchBase : ITorchBase
{
/// <summary>
/// Dirty hack because *keen*
/// Use only if absolutely necessary.
/// </summary>
[Obsolete]
public static ITorchBase Instance { get; private set; }
protected static Logger Log = LogManager.GetLogger("Torch");
public string[] RunArgs { get; set; }
public IPluginManager Plugins { get; protected set; }
public IMultiplayer Multiplayer { get; protected set; }
public event Action SessionLoaded;
private bool _init;
protected void InvokeSessionLoaded()
{
SessionLoaded?.Invoke();
}
protected TorchBase()
{
if (Instance != null)
throw new InvalidOperationException("A TorchBase instance already exists.");
Instance = this;
RunArgs = new string[0];
Plugins = new PluginManager(this);
Multiplayer = new MultiplayerManager(this);
}
/// <summary>
/// Invokes an action on the game thread.
/// </summary>
/// <param name="action"></param>
public void Invoke(Action action)
{
MySandboxGame.Static.Invoke(action);
}
/// <summary>
/// Invokes an action on the game thread asynchronously.
/// </summary>
/// <param name="action"></param>
public Task InvokeAsync(Action action)
{
if (Thread.CurrentThread == MySandboxGame.Static.UpdateThread)
{
Debug.Assert(false, $"{nameof(InvokeAsync)} should not be called on the game thread.");
action?.Invoke();
return Task.CompletedTask;
}
return Task.Run(() => InvokeBlocking(action));
}
/// <summary>
/// Invokes an action on the game thread and blocks until it is completed.
/// </summary>
/// <param name="action"></param>
public void InvokeBlocking(Action action)
{
if (action == null)
return;
if (Thread.CurrentThread == MySandboxGame.Static.UpdateThread)
{
Debug.Assert(false, $"{nameof(InvokeBlocking)} should not be called on the game thread.");
action.Invoke();
return;
}
var e = new AutoResetEvent(false);
MySandboxGame.Static.Invoke(() =>
{
try
{
action.Invoke();
}
catch (Exception ex)
{
//log
}
finally
{
e.Set();
}
});
if (!e.WaitOne(60000))
throw new TimeoutException("The game action timed out.");
}
public virtual void Init()
{
Debug.Assert(!_init, "Torch instance is already initialized.");
_init = true;
MyScriptCompiler.Static.AddConditionalCompilationSymbols("TORCH");
MyScriptCompiler.Static.AddReferencedAssemblies(typeof(ITorchBase).Assembly.Location);
MyScriptCompiler.Static.AddReferencedAssemblies(typeof(TorchBase).Assembly.Location);
}
public abstract void Start();
public abstract void Stop();
}
}