Files
se-launcher/PluginLoader/Data/PluginData.cs
2022-10-29 02:02:14 +07:00

220 lines
6.5 KiB
C#

using System.Diagnostics;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Xml.Serialization;
using PluginLoader.GUI;
using ProtoBuf;
using Sandbox.Graphics.GUI;
using VRage;
using VRage.Utils;
namespace PluginLoader.Data;
[XmlInclude(typeof(WorkshopPlugin))]
[XmlInclude(typeof(SEPMPlugin))]
[XmlInclude(typeof(GitHubPlugin))]
[XmlInclude(typeof(ModPlugin))]
[ProtoContract]
[ProtoInclude(100, typeof(SteamPlugin))]
[ProtoInclude(103, typeof(GitHubPlugin))]
[ProtoInclude(104, typeof(ModPlugin))]
public abstract class PluginData : IEquatable<PluginData>
{
public abstract string Source { get; }
[XmlIgnore] public Version Version { get; protected set; }
[XmlIgnore] public virtual PluginStatus Status { get; set; } = PluginStatus.None;
public virtual string StatusString
{
get
{
switch (Status)
{
case PluginStatus.PendingUpdate:
return "Pending Update";
case PluginStatus.Updated:
return "Updated";
case PluginStatus.Error:
return "Error!";
case PluginStatus.Blocked:
return "Not whitelisted!";
default:
return "";
}
}
}
[XmlIgnore] public bool IsLocal => Source == MyTexts.GetString(MyCommonTexts.Local);
[ProtoMember(1)] public virtual string Id { get; set; }
[ProtoMember(2)] public string FriendlyName { get; set; } = "Unknown";
[ProtoMember(3)] public bool Hidden { get; set; } = false;
[ProtoMember(4)] public string GroupId { get; set; }
[ProtoMember(5)] public string Tooltip { get; set; }
[ProtoMember(6)] public string Author { get; set; }
[ProtoMember(7)] public string Description { get; set; }
[XmlIgnore] public List<PluginData> Group { get; } = new();
[XmlIgnore] public bool Enabled => Main.Instance.Config.IsEnabled(Id);
public bool Equals(PluginData other)
{
return other != null &&
Id == other.Id;
}
public abstract Assembly GetAssembly();
public virtual bool TryLoadAssembly(out Assembly a)
{
if (Status == PluginStatus.Error)
{
a = null;
return false;
}
try
{
// Get the file path
a = GetAssembly();
if (Status == PluginStatus.Blocked)
return false;
if (a == null)
{
LogFile.WriteLine("Failed to load " + ToString());
Error();
return false;
}
return true;
}
catch (Exception e)
{
var name = ToString();
LogFile.WriteLine($"Failed to load {name} because of an error: " + e);
if (e is MissingMemberException)
LogFile.WriteLine($"Is {name} up to date?");
if (e is NotSupportedException && e.Message.Contains("loadFromRemoteSources"))
Error($"The plugin {name} was blocked by windows. Please unblock the file in the dll file properties.");
else
Error();
a = null;
return false;
}
}
public override bool Equals(object obj)
{
return Equals(obj as PluginData);
}
public override int GetHashCode()
{
return 2108858624 + EqualityComparer<string>.Default.GetHashCode(Id);
}
public static bool operator ==(PluginData left, PluginData right)
{
return EqualityComparer<PluginData>.Default.Equals(left, right);
}
public static bool operator !=(PluginData left, PluginData right)
{
return !(left == right);
}
public override string ToString()
{
return Id + '|' + FriendlyName;
}
public void Error(string msg = null)
{
Status = PluginStatus.Error;
if (msg == null)
msg =
$"The plugin '{this}' caused an error. It is recommended that you disable this plugin and restart. The game may be unstable beyond this point. See loader.log or the game log for details.";
var file = MyLog.Default.GetFilePath();
if (File.Exists(file) && file.EndsWith(".log"))
{
MyLog.Default.Flush();
msg += "\n\nWould you like to open the game log?";
var result = LoaderTools.ShowMessageBox(msg, "Plugin Loader", MessageBoxButtons.YesNo,
MessageBoxIcon.Error);
if (result == DialogResult.Yes)
Process.Start(file);
}
else
{
LoaderTools.ShowMessageBox(msg, "Plugin Loader", MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
}
protected void ErrorSecurity(string hash)
{
Status = PluginStatus.Blocked;
LoaderTools.ShowMessageBox($"Unable to load the plugin {this} because it is not whitelisted!",
"Plugin Loader", MessageBoxButtons.OK, MessageBoxIcon.Error);
LogFile.WriteLine("Error: " + this + " with an sha256 of " + hash + " is not on the whitelist!");
}
public abstract void Show();
public virtual void GetDescriptionText(MyGuiControlMultilineText textbox)
{
textbox.Visible = true;
textbox.Clear();
if (string.IsNullOrEmpty(Description))
{
if (string.IsNullOrEmpty(Tooltip))
textbox.AppendText("No description");
else
textbox.AppendText(CapLength(Tooltip, 1000));
return;
}
var text = CapLength(Description, 1000);
var textStart = 0;
foreach (Match m in Regex.Matches(text, @"https?:\/\/(www\.)?[\w-.]{2,256}\.[a-z]{2,4}\b[\w-.@:%\+~#?&//=]*"))
{
var textLen = m.Index - textStart;
if (textLen > 0)
textbox.AppendText(text.Substring(textStart, textLen));
textbox.AppendLink(m.Value, m.Value);
textStart = m.Index + m.Length;
}
if (textStart < text.Length)
textbox.AppendText(text.Substring(textStart));
}
private string CapLength(string s, int len)
{
if (s.Length > len)
return s.Substring(0, len);
return s;
}
public virtual bool OpenContextMenu(MyGuiControlContextMenu menu)
{
return false;
}
public virtual void ContextMenuClicked(MyGuiScreenPluginConfig screen, MyGuiControlContextMenu.EventArgs args)
{
}
}