Files
se-launcher/PluginLoader/PluginInstance.cs

176 lines
4.5 KiB
C#

using System.Reflection;
using HarmonyLib;
using PluginLoader.Data;
using Sandbox.Game.World;
using VRage.Game.Components;
using VRage.Plugins;
using SEPMPlugin = PluginLoader.SEPM.SEPMPlugin;
namespace PluginLoader;
public class PluginInstance
{
private readonly PluginData data;
private readonly Assembly? mainAssembly;
private readonly Type mainType;
private IHandleInputPlugin inputPlugin;
private MethodInfo openConfigDialog;
private IPlugin plugin;
private PluginInstance(PluginData data, Assembly? mainAssembly, Type mainType)
{
this.data = data;
this.mainAssembly = mainAssembly;
this.mainType = mainType;
}
public string Id => data.Id;
public bool HasConfigDialog => openConfigDialog != null;
public bool Instantiate()
{
try
{
plugin = (IPlugin)Activator.CreateInstance(mainType);
inputPlugin = plugin as IHandleInputPlugin;
}
catch (Exception e)
{
ThrowError($"Failed to instantiate {data} because of an error: {e}");
return false;
}
try
{
openConfigDialog = AccessTools.DeclaredMethod(mainType, "OpenConfigDialog", Array.Empty<Type>());
}
catch (Exception e)
{
LogFile.WriteLine($"Unable to find OpenConfigDialog() in {data} due to an error: {e}");
openConfigDialog = null;
}
return true;
}
public void OpenConfig()
{
if (plugin == null || openConfigDialog == null)
return;
try
{
openConfigDialog.Invoke(plugin, Array.Empty<object>());
}
catch (Exception e)
{
ThrowError($"Failed to open plugin config for {data} because of an error: {e}");
}
}
public bool Init(object gameInstance)
{
if (plugin == null)
return false;
try
{
if (plugin is SEPMPlugin sepm)
LoaderTools.ExecuteMain(sepm);
plugin.Init(gameInstance);
return true;
}
catch (Exception e)
{
ThrowError($"Failed to initialize {data} because of an error: {e}");
return false;
}
}
public void RegisterSession(MySession session)
{
if (plugin != null)
try
{
var descType = typeof(MySessionComponentDescriptor);
var count = 0;
foreach (var t in mainAssembly.GetTypes().Where(t => Attribute.IsDefined(t, descType)))
{
var comp = (MySessionComponentBase)Activator.CreateInstance(t);
session.RegisterComponent(comp, comp.UpdateOrder, comp.Priority);
count++;
}
if (count > 0)
LogFile.WriteLine($"Registered {count} session components from: {mainAssembly.FullName}");
}
catch (Exception e)
{
ThrowError($"Failed to register {data} because of an error: {e}");
}
}
public bool Update()
{
if (plugin == null)
return false;
plugin.Update();
return true;
}
public bool HandleInput()
{
if (plugin == null)
return false;
inputPlugin?.HandleInput();
return true;
}
public void Dispose()
{
if (plugin != null)
try
{
plugin.Dispose();
plugin = null;
inputPlugin = null;
}
catch (Exception e)
{
data.Status = PluginStatus.Error;
LogFile.WriteLine($"Failed to dispose {data} because of an error: {e}");
}
}
private void ThrowError(string error)
{
LogFile.WriteLine(error);
data.Error();
Dispose();
}
public static bool TryGet(PluginData data, out PluginInstance instance)
{
instance = null;
if (data.Status == PluginStatus.Error || !data.TryLoadAssembly(out var a))
return false;
var pluginType = a.GetTypes().FirstOrDefault(t => typeof(IPlugin).IsAssignableFrom(t));
if (pluginType == null)
{
LogFile.WriteLine($"Failed to load {data} because it does not contain an IPlugin");
data.Error();
return false;
}
instance = new(data, a, pluginType);
return true;
}
public override string ToString()
{
return data.ToString();
}
}