using System; using System.Collections.Generic; using System.IO; using System.Linq; using Compression.BSA; using MessagePack; using Wabbajack.Common; using Wabbajack.Lib.Downloaders; using Wabbajack.VirtualFileSystem; namespace Wabbajack.Lib { public class RawSourceFile { public readonly RelativePath Path; public RawSourceFile(VirtualFile file, RelativePath path) { File = file; Path = path; } public AbsolutePath AbsolutePath => File.StagedPath; public VirtualFile File { get; } public Hash Hash => File.Hash; public T EvolveTo() where T : Directive, new() { var v = new T(); v.To = Path; v.Hash = Hash; v.Size = File.Size; return v; } } [MessagePackObject] public class ModList { /// /// Archives required by this modlist /// [Key(0)] public List Archives; /// /// Author of the ModList /// [Key(1)] public string Author; /// /// Description of the ModList /// [Key(2)] public string Description; /// /// Install directives /// [Key(3)] public List Directives; /// /// The game variant to which this game applies /// [Key(4)] public Game GameType; /// /// Hash of the banner-image /// [Key(5)] public RelativePath Image; /// /// The Mod Manager used to create the modlist /// [Key(6)] public ModManager ModManager; /// /// Name of the ModList /// [Key(7)] public string Name; /// /// readme path or website /// [Key(8)] public string Readme; /// /// Whether readme is a website /// [Key(9)] public bool ReadmeIsWebsite; /// /// The build version of Wabbajack used when compiling the Modlist /// [Key(10)] public Version WabbajackVersion; /// /// Website of the ModList /// [Key(11)] public Uri Website; /// /// The size of all the archives once they're downloaded /// [IgnoreMember] public long DownloadSize => Archives.Sum(a => a.Size); /// /// The size of all the files once they are installed (excluding downloaded archives) /// [IgnoreMember] public long InstallSize => Directives.Sum(s => s.Size); public ModList Clone() { using var ms = new MemoryStream(); ms.WriteAsMessagePack(this); ms.Position = 0; return ms.ReadAsMessagePack(); } } [MessagePackObject] [Union(0, typeof(ArchiveMeta))] [Union(1, typeof(CreateBSA))] [Union(2, typeof(FromArchive))] [Union(3, typeof(MergedPatch))] [Union(4, typeof(InlineFile))] [Union(5, typeof(PatchedFromArchive))] [Union(6, typeof(RemappedInlineFile))] [Union(7, typeof(CleanedESM))] public abstract class Directive { [Key(0)] public Hash Hash { get; set; } [Key(1)] public long Size { get; set; } /// /// location the file will be copied to, relative to the install path. /// [Key(2)] public RelativePath To { get; set; } } public class IgnoredDirectly : Directive { public string Reason; } public class NoMatch : IgnoredDirectly { } [MessagePackObject] public class InlineFile : Directive { /// /// Data that will be written as-is to the destination location; /// [Key(3)] public RelativePath SourceDataID { get; set; } } [MessagePackObject] public class ArchiveMeta : Directive { [Key(3)] public RelativePath SourceDataID { get; set; } } public enum PropertyType { Banner, Readme } /// /// File meant to be extracted before the installation /// [MessagePackObject] public class PropertyFile : InlineFile { [Key(4)] public PropertyType Type; } [MessagePackObject] public class CleanedESM : InlineFile { [Key(4)] public Hash SourceESMHash; } /// /// A file that has the game and MO2 folders remapped on installation /// [MessagePackObject] public class RemappedInlineFile : InlineFile { } [MessagePackObject] public class SteamMeta : ArchiveMeta { [Key(4)] public int ItemID { get; set; } } [MessagePackObject] public class FromArchive : Directive { private string _fullPath; [Key(3)] public HashRelativePath ArchiveHashPath { get; set; } [IgnoreMember] public VirtualFile FromFile { get; set; } [IgnoreMember] public string FullPath => _fullPath ??= string.Join("|", ArchiveHashPath); } [MessagePackObject] public class CreateBSA : Directive { [Key(3)] public RelativePath TempID { get; set; } [Key(4)] public ArchiveStateObject State { get; set; } [Key(5)] public List FileStates { get; set; } } [MessagePackObject] public class PatchedFromArchive : FromArchive { [Key(4)] public Hash FromHash { get; set; } /// /// The file to apply to the source file to patch it /// [Key(5)] public RelativePath PatchID { get; set; } } [MessagePackObject] public class SourcePatch { [Key(0)] public Hash Hash { get; set; } [Key(1)] public RelativePath RelativePath { get; set; } } [MessagePackObject] public class MergedPatch : Directive { [Key(3)] public RelativePath PatchID { get; set; } [Key(4)] public List Sources { get; set; } } [MessagePackObject] public class Archive { /// /// xxHash64 of the archive /// [Key(0)] public Hash Hash { get; set; } /// /// Meta INI for the downloaded archive /// [Key(1)] public string Meta { get; set; } /// /// Human friendly name of this archive /// [Key(2)] public string Name { get; set; } [Key(3)] public long Size { get; set; } [Key(4)] public AbstractDownloadState State { get; set; } } public class IndexedArchive { public dynamic IniData; public string Meta; public string Name; public VirtualFile File { get; internal set; } } /// /// A archive entry /// public class IndexedEntry { /// /// MurMur3 hash of this file /// public string Hash; /// /// Path in the archive to this file /// public string Path; /// /// Size of the file (uncompressed) /// public long Size; } public class IndexedArchiveEntry : IndexedEntry { public string[] HashPath; } }