using System.Reflection; using System.Xml.Serialization; using ProtoBuf; using Sandbox.Graphics.GUI; namespace PluginLoader.Data; [ProtoContract] [ProtoInclude(101, typeof(SEPMPlugin))] [ProtoInclude(102, typeof(WorkshopPlugin))] public abstract class SteamPlugin : PluginData, ISteamItem { protected string root, sourceFile, hashFile; [XmlArray] [ProtoMember(1)] public string[] AllowedHashes { get; set; } protected abstract string HashFile { get; } [XmlIgnore] public ulong WorkshopId { get; private set; } public override string Id { get => base.Id; set { base.Id = value; WorkshopId = ulong.Parse(Id); } } public void Init(string sourceFile) { Status = PluginStatus.None; this.sourceFile = sourceFile; root = Path.GetDirectoryName(sourceFile); hashFile = Path.Combine(root, HashFile); CheckForUpdates(); } protected virtual void CheckForUpdates() { if (File.Exists(hashFile)) { var oldHash = File.ReadAllText(hashFile); var newHash = LoaderTools.GetHash1(sourceFile); if (oldHash != newHash) Status = PluginStatus.PendingUpdate; } else { Status = PluginStatus.PendingUpdate; } } public override Assembly? GetAssembly() { if (Status == PluginStatus.PendingUpdate) { LogFile.Log.Debug("Updating " + this); ApplyUpdate(); if (Status == PluginStatus.PendingUpdate) { File.WriteAllText(hashFile, LoaderTools.GetHash1(sourceFile)); Status = PluginStatus.Updated; } else { return null; } } var dll = GetAssemblyFile(); if (dll == null || !File.Exists(dll)) return null; if (!VerifyAllowed(dll)) return null; var a = Assembly.LoadFile(dll); Version = a.GetName().Version; return a; } protected abstract void ApplyUpdate(); protected abstract string GetAssemblyFile(); public override void Show() { MyGuiSandbox.OpenUrl("https://steamcommunity.com/workshop/filedetails/?id=" + Id, UrlOpenMode.SteamOrExternalWithConfirm); } private bool VerifyAllowed(string dll) { if (AllowedHashes == null || AllowedHashes.Length == 0) return true; var hash = LoaderTools.GetHash256(dll); foreach (var s in AllowedHashes) if (s == hash) return true; ErrorSecurity(hash); return false; } }