mirror of
https://github.com/wabbajack-tools/wabbajack.git
synced 2024-08-30 18:42:17 +00:00
MessagePack, and basic sanity test passes
This commit is contained in:
parent
3b895f4dbb
commit
d6123a7fb2
@ -37,6 +37,12 @@ namespace Wabbajack.Common.Http
|
||||
return await SendStringAsync(request);
|
||||
}
|
||||
|
||||
public async Task<string> GetStringAsync(Uri url)
|
||||
{
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, url);
|
||||
return await SendStringAsync(request);
|
||||
}
|
||||
|
||||
public async Task<string> DeleteStringAsync(string url)
|
||||
{
|
||||
var request = new HttpRequestMessage(HttpMethod.Delete, url);
|
||||
|
91
Wabbajack.Common/MessagePack.cs
Normal file
91
Wabbajack.Common/MessagePack.cs
Normal file
@ -0,0 +1,91 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using MessagePack;
|
||||
using MessagePack.Formatters;
|
||||
using MessagePack.Resolvers;
|
||||
|
||||
namespace Wabbajack.Common
|
||||
{
|
||||
public partial class Utils
|
||||
{
|
||||
private static MessagePackSerializerOptions _messagePackOptions;
|
||||
private static IFormatterResolver _resolver;
|
||||
|
||||
private static void MessagePackInit()
|
||||
{
|
||||
_resolver = CompositeResolver.Create(
|
||||
new List<IMessagePackFormatter>{new HashFormatter()},
|
||||
new List<IFormatterResolver> {StandardResolver.Instance}
|
||||
);
|
||||
_messagePackOptions = MessagePackSerializerOptions.Standard
|
||||
.WithResolver(_resolver)
|
||||
.WithCompression(MessagePackCompression.Lz4BlockArray);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a object to this stream using MessagePack
|
||||
/// </summary>
|
||||
/// <param name="stream"></param>
|
||||
/// <param name="obj"></param>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public static async Task WriteAsMessagePackAsync<T>(this Stream stream, T obj)
|
||||
{
|
||||
await MessagePackSerializer.SerializeAsync(stream, obj, _messagePackOptions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a object to this stream using MessagePack
|
||||
/// </summary>
|
||||
/// <param name="stream"></param>
|
||||
/// <param name="obj"></param>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public static void WriteAsMessagePack<T>(this Stream stream, T obj)
|
||||
{
|
||||
MessagePackSerializer.Serialize(stream, obj, _messagePackOptions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a object from this stream using MessagePack
|
||||
/// </summary>
|
||||
/// <param name="stream"></param>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public static async Task<T> ReadAsMessagePackAsync<T>(this Stream stream)
|
||||
{
|
||||
return await MessagePackSerializer.DeserializeAsync<T>(stream, _messagePackOptions);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Reads a object from this stream using MessagePack
|
||||
/// </summary>
|
||||
/// <param name="stream"></param>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public static T ReadAsMessagePack<T>(this Stream stream)
|
||||
{
|
||||
return MessagePackSerializer.Deserialize<T>(stream, _messagePackOptions);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#region Formatters
|
||||
|
||||
public class HashFormatter : IMessagePackFormatter<Hash>
|
||||
{
|
||||
public void Serialize(ref MessagePackWriter writer, Hash value, MessagePackSerializerOptions options)
|
||||
{
|
||||
writer.WriteUInt64((ulong)value);
|
||||
}
|
||||
|
||||
public Hash Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
|
||||
{
|
||||
return new Hash(reader.ReadUInt64());
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
@ -6,7 +6,6 @@ using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Reactive.Linq;
|
||||
using System.Reactive.Subjects;
|
||||
using System.Reflection;
|
||||
@ -16,7 +15,6 @@ using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Alphaleonis.Win32.Filesystem;
|
||||
using Ceras;
|
||||
using ICSharpCode.SharpZipLib.BZip2;
|
||||
using IniParser;
|
||||
using Newtonsoft.Json;
|
||||
@ -52,6 +50,8 @@ namespace Wabbajack.Common
|
||||
|
||||
static Utils()
|
||||
{
|
||||
MessagePackInit();
|
||||
|
||||
if (!Directory.Exists(Consts.LocalAppDataPath))
|
||||
Directory.CreateDirectory(Consts.LocalAppDataPath);
|
||||
|
||||
@ -343,43 +343,6 @@ namespace Wabbajack.Common
|
||||
return new DynamicIniData(new FileIniDataParser().ReadData(new StreamReader(new MemoryStream(Encoding.UTF8.GetBytes(file)))));
|
||||
}
|
||||
|
||||
public static void ToCERAS<T>(this T obj, string filename, SerializerConfig config)
|
||||
{
|
||||
byte[] final;
|
||||
final = ToCERAS(obj, config);
|
||||
File.WriteAllBytes(filename, final);
|
||||
}
|
||||
|
||||
public static byte[] ToCERAS<T>(this T obj, SerializerConfig config)
|
||||
{
|
||||
byte[] final;
|
||||
var ceras = new CerasSerializer(config);
|
||||
byte[] buffer = null;
|
||||
ceras.Serialize(obj, ref buffer);
|
||||
|
||||
using (var m1 = new MemoryStream(buffer))
|
||||
using (var m2 = new MemoryStream())
|
||||
{
|
||||
BZip2.Compress(m1, m2, false, 9);
|
||||
m2.Seek(0, SeekOrigin.Begin);
|
||||
final = m2.ToArray();
|
||||
}
|
||||
return final;
|
||||
}
|
||||
|
||||
public static T FromCERAS<T>(this Stream data, SerializerConfig config)
|
||||
{
|
||||
var ceras = new CerasSerializer(config);
|
||||
byte[] bytes = data.ReadAll();
|
||||
using (var m1 = new MemoryStream(bytes))
|
||||
using (var m2 = new MemoryStream())
|
||||
{
|
||||
BZip2.Decompress(m1, m2, false);
|
||||
m2.Seek(0, SeekOrigin.Begin);
|
||||
return ceras.Deserialize<T>(m2.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
public static void ToJSON<T>(this T obj, string filename)
|
||||
{
|
||||
if (File.Exists(filename))
|
||||
@ -388,18 +351,6 @@ namespace Wabbajack.Common
|
||||
JsonConvert.SerializeObject(obj, Formatting.Indented,
|
||||
new JsonSerializerSettings {TypeNameHandling = TypeNameHandling.Auto}));
|
||||
}
|
||||
/*
|
||||
public static void ToBSON<T>(this T obj, string filename)
|
||||
{
|
||||
using (var fo = File.Open(filename, System.IO.FileMode.Create))
|
||||
using (var br = new BsonDataWriter(fo))
|
||||
{
|
||||
fo.SetLength(0);
|
||||
var serializer = JsonSerializer.Create(new JsonSerializerSettings
|
||||
{TypeNameHandling = TypeNameHandling.Auto});
|
||||
serializer.Serialize(br, obj);
|
||||
}
|
||||
}*/
|
||||
|
||||
public static ulong ToMilliseconds(this DateTime date)
|
||||
{
|
||||
@ -1179,7 +1130,7 @@ namespace Wabbajack.Common
|
||||
});
|
||||
}
|
||||
|
||||
public static void OpenWebsite(string url)
|
||||
public static void OpenWebsite(Uri url)
|
||||
{
|
||||
Process.Start(new ProcessStartInfo("cmd.exe", $"/c start {url}")
|
||||
{
|
||||
|
@ -26,7 +26,6 @@
|
||||
<Folder Include="Properties\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Ceras" Version="4.1.7" />
|
||||
<PackageReference Include="Genbox.AlphaFS" Version="2.2.2.1" />
|
||||
<PackageReference Include="ini-parser-netstandard" Version="2.5.2" />
|
||||
<PackageReference Include="MessagePack" Version="2.1.90" />
|
||||
|
@ -9,6 +9,7 @@ using Wabbajack.Common;
|
||||
using Wabbajack.Lib.CompilationSteps;
|
||||
using Wabbajack.Lib.Downloaders;
|
||||
using Wabbajack.Lib.ModListRegistry;
|
||||
using Wabbajack.Lib.Validation;
|
||||
using Wabbajack.VirtualFileSystem;
|
||||
using Directory = Alphaleonis.Win32.Filesystem.Directory;
|
||||
using File = Alphaleonis.Win32.Filesystem.File;
|
||||
@ -20,7 +21,7 @@ namespace Wabbajack.Lib
|
||||
{
|
||||
public string ModListName, ModListAuthor, ModListDescription, ModListImage, ModListWebsite, ModListReadme;
|
||||
public bool ReadmeIsWebsite;
|
||||
public string WabbajackVersion;
|
||||
protected Version WabbajackVersion;
|
||||
|
||||
public abstract string VFSCacheName { get; }
|
||||
//protected string VFSCacheName => Path.Combine(Consts.LocalAppDataPath, $"vfs_compile_cache.bin");
|
||||
@ -122,7 +123,8 @@ namespace Wabbajack.Lib
|
||||
|
||||
ModList.ReadmeIsWebsite = ReadmeIsWebsite;
|
||||
|
||||
ModList.ToCERAS(Path.Combine(ModListOutputFolder, "modlist"), CerasConfig.Config);
|
||||
using (var of = File.Create(Path.Combine(ModListOutputFolder, "modlist")))
|
||||
of.WriteAsMessagePack(ModList);
|
||||
|
||||
if (File.Exists(ModListOutputFile))
|
||||
File.Delete(ModListOutputFile);
|
||||
|
@ -82,7 +82,7 @@ namespace Wabbajack.Lib
|
||||
return e.FromJSON<ModList>();
|
||||
}
|
||||
using (var e = entry.Open())
|
||||
return e.FromCERAS<ModList>(CerasConfig.Config);
|
||||
return e.ReadAsMessagePack<ModList>();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,39 +0,0 @@
|
||||
using Ceras;
|
||||
using Compression.BSA;
|
||||
using Wabbajack.Common;
|
||||
using Wabbajack.Lib.Downloaders;
|
||||
using Wabbajack.VirtualFileSystem;
|
||||
|
||||
namespace Wabbajack.Lib
|
||||
{
|
||||
public class CerasConfig
|
||||
{
|
||||
public static readonly SerializerConfig Config;
|
||||
|
||||
static CerasConfig()
|
||||
{
|
||||
Config = new SerializerConfig
|
||||
{
|
||||
KnownTypes =
|
||||
{
|
||||
typeof(ModList), typeof(Game), typeof(Directive), typeof(IgnoredDirectly),
|
||||
typeof(NoMatch), typeof(InlineFile), typeof(PropertyType), typeof(CleanedESM),
|
||||
typeof(RemappedInlineFile), typeof(FromArchive), typeof(CreateBSA), typeof(PatchedFromArchive),
|
||||
typeof(SourcePatch), typeof(MergedPatch), typeof(Archive), typeof(IndexedArchive), typeof(IndexedEntry),
|
||||
typeof(IndexedArchiveEntry), typeof(BSAIndexedEntry), typeof(VirtualFile),
|
||||
typeof(ArchiveStateObject), typeof(FileStateObject), typeof(IDownloader),
|
||||
typeof(IUrlDownloader), typeof(AbstractDownloadState), typeof(ManualDownloader.State),
|
||||
typeof(DropboxDownloader), typeof(GoogleDriveDownloader.State), typeof(HTTPDownloader.State),
|
||||
typeof(MegaDownloader.State), typeof(ModDBDownloader.State), typeof(NexusDownloader.State),
|
||||
typeof(BSAStateObject), typeof(BSAFileStateObject), typeof(BA2StateObject), typeof(BA2DX10EntryState),
|
||||
typeof(BA2FileEntryState), typeof(MediaFireDownloader.State), typeof(ArchiveMeta),
|
||||
typeof(PropertyFile), typeof(SteamMeta), typeof(SteamWorkshopDownloader), typeof(SteamWorkshopDownloader.State),
|
||||
typeof(LoversLabDownloader.State), typeof(GameFileSourceDownloader.State), typeof(VectorPlexusDownloader.State),
|
||||
typeof(DeadlyStreamDownloader.State), typeof(AFKModsDownloader.State), typeof(TESAllianceDownloader.State),
|
||||
typeof(TES3ArchiveState), typeof(TES3FileState), typeof(BethesdaNetDownloader.State), typeof(YouTubeDownloader), typeof(IMetaState)
|
||||
},
|
||||
};
|
||||
Config.VersionTolerance.Mode = VersionToleranceMode.Standard;
|
||||
}
|
||||
}
|
||||
}
|
@ -2,8 +2,8 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Ceras;
|
||||
using Compression.BSA;
|
||||
using MessagePack;
|
||||
using Wabbajack.Common;
|
||||
using Wabbajack.Lib.Downloaders;
|
||||
using Wabbajack.VirtualFileSystem;
|
||||
@ -38,99 +38,122 @@ namespace Wabbajack.Lib
|
||||
}
|
||||
}
|
||||
|
||||
[MessagePackObject]
|
||||
public class ModList
|
||||
{
|
||||
/// <summary>
|
||||
/// Archives required by this modlist
|
||||
/// </summary>
|
||||
[Key(0)]
|
||||
public List<Archive> Archives;
|
||||
|
||||
/// <summary>
|
||||
/// The Mod Manager used to create the modlist
|
||||
/// </summary>
|
||||
public ModManager ModManager;
|
||||
|
||||
/// <summary>
|
||||
/// The game variant to which this game applies
|
||||
/// </summary>
|
||||
public Game GameType;
|
||||
|
||||
/// <summary>
|
||||
/// The build version of Wabbajack used when compiling the Modlist
|
||||
/// </summary>
|
||||
public string WabbajackVersion;
|
||||
|
||||
/// <summary>
|
||||
/// Install directives
|
||||
/// </summary>
|
||||
public List<Directive> Directives;
|
||||
|
||||
/// <summary>
|
||||
/// Name of the ModList
|
||||
/// </summary>
|
||||
public string Name;
|
||||
|
||||
/// <summary>
|
||||
/// Author of the ModList
|
||||
/// </summary>
|
||||
[Key(1)]
|
||||
public string Author;
|
||||
|
||||
/// <summary>
|
||||
/// Description of the ModList
|
||||
/// </summary>
|
||||
[Key(2)]
|
||||
public string Description;
|
||||
|
||||
/// <summary>
|
||||
/// Install directives
|
||||
/// </summary>
|
||||
[Key(3)]
|
||||
public List<Directive> Directives;
|
||||
|
||||
/// <summary>
|
||||
/// The game variant to which this game applies
|
||||
/// </summary>
|
||||
[Key(4)]
|
||||
public Game GameType;
|
||||
|
||||
/// <summary>
|
||||
/// Hash of the banner-image
|
||||
/// </summary>
|
||||
[Key(5)]
|
||||
public string Image;
|
||||
|
||||
/// <summary>
|
||||
/// Website of the ModList
|
||||
/// The Mod Manager used to create the modlist
|
||||
/// </summary>
|
||||
public string Website;
|
||||
[Key(6)]
|
||||
public ModManager ModManager;
|
||||
|
||||
/// <summary>
|
||||
/// Name of the ModList
|
||||
/// </summary>
|
||||
[Key(7)]
|
||||
public string Name;
|
||||
|
||||
/// <summary>
|
||||
/// readme path or website
|
||||
/// </summary>
|
||||
[Key(8)]
|
||||
public string Readme;
|
||||
|
||||
/// <summary>
|
||||
/// The size of all the archives once they're downloaded
|
||||
/// </summary>
|
||||
public long DownloadSize => Archives.Sum(a => a.Size);
|
||||
|
||||
/// <summary>
|
||||
/// The size of all the files once they are installed (excluding downloaded archives)
|
||||
/// </summary>
|
||||
public long InstallSize => Directives.Sum(s => s.Size);
|
||||
|
||||
/// <summary>
|
||||
/// Estimate of the amount of space required in the VFS staging folders during installation
|
||||
/// </summary>
|
||||
public long ScratchSpaceSize => Archives.OrderByDescending(a => a.Size)
|
||||
.Take(Environment.ProcessorCount)
|
||||
.Sum(a => a.Size) * 2;
|
||||
|
||||
/// <summary>
|
||||
/// Whether readme is a website
|
||||
/// </summary>
|
||||
[Key(9)]
|
||||
public bool ReadmeIsWebsite;
|
||||
|
||||
/// <summary>
|
||||
/// The build version of Wabbajack used when compiling the Modlist
|
||||
/// </summary>
|
||||
[Key(10)]
|
||||
public Version WabbajackVersion;
|
||||
|
||||
/// <summary>
|
||||
/// Website of the ModList
|
||||
/// </summary>
|
||||
[Key(11)]
|
||||
public Uri Website;
|
||||
|
||||
/// <summary>
|
||||
/// The size of all the archives once they're downloaded
|
||||
/// </summary>
|
||||
[IgnoreMember]
|
||||
public long DownloadSize => Archives.Sum(a => a.Size);
|
||||
|
||||
/// <summary>
|
||||
/// The size of all the files once they are installed (excluding downloaded archives)
|
||||
/// </summary>
|
||||
[IgnoreMember]
|
||||
public long InstallSize => Directives.Sum(s => s.Size);
|
||||
|
||||
public ModList Clone()
|
||||
{
|
||||
return new MemoryStream(this.ToCERAS(CerasConfig.Config)).FromCERAS<ModList>(CerasConfig.Config);
|
||||
using var ms = new MemoryStream();
|
||||
ms.WriteAsMessagePack(this);
|
||||
ms.Position = 0;
|
||||
return ms.ReadAsMessagePack<ModList>();
|
||||
}
|
||||
}
|
||||
|
||||
public class Directive
|
||||
[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))]
|
||||
public abstract class Directive
|
||||
{
|
||||
[Key(0)]
|
||||
public Hash Hash { get; set; }
|
||||
[Key(1)]
|
||||
public long Size { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// location the file will be copied to, relative to the install path.
|
||||
/// </summary>
|
||||
public string To;
|
||||
public long Size;
|
||||
public Hash Hash;
|
||||
[Key(2)]
|
||||
public string To { get; set; }
|
||||
}
|
||||
|
||||
public class IgnoredDirectly : Directive
|
||||
@ -142,17 +165,21 @@ namespace Wabbajack.Lib
|
||||
{
|
||||
}
|
||||
|
||||
[MessagePackObject]
|
||||
public class InlineFile : Directive
|
||||
{
|
||||
/// <summary>
|
||||
/// Data that will be written as-is to the destination location;
|
||||
/// </summary>
|
||||
[Key(3)]
|
||||
public string SourceDataID;
|
||||
}
|
||||
|
||||
[MessagePackObject]
|
||||
public class ArchiveMeta : Directive
|
||||
{
|
||||
public string SourceDataID;
|
||||
[Key(3)]
|
||||
public string SourceDataID { get; set; }
|
||||
}
|
||||
|
||||
public enum PropertyType { Banner, Readme }
|
||||
@ -173,82 +200,100 @@ namespace Wabbajack.Lib
|
||||
/// <summary>
|
||||
/// A file that has the game and MO2 folders remapped on installation
|
||||
/// </summary>
|
||||
[MessagePackObject]
|
||||
public class RemappedInlineFile : InlineFile
|
||||
{
|
||||
}
|
||||
|
||||
[MessagePackObject]
|
||||
public class SteamMeta : ArchiveMeta
|
||||
{
|
||||
public int ItemID;
|
||||
/// <summary>
|
||||
/// Size is in bytes
|
||||
/// </summary>
|
||||
public int Size;
|
||||
[Key(4)]
|
||||
public int ItemID { get; set; }
|
||||
}
|
||||
|
||||
[MemberConfig(TargetMember.All)]
|
||||
[MessagePackObject]
|
||||
public class FromArchive : Directive
|
||||
{
|
||||
private string _fullPath;
|
||||
|
||||
public string[] ArchiveHashPath;
|
||||
[Key(3)]
|
||||
public string[] ArchiveHashPath { get; set; }
|
||||
|
||||
[Exclude]
|
||||
public VirtualFile FromFile;
|
||||
[IgnoreMember]
|
||||
public VirtualFile FromFile { get; set; }
|
||||
|
||||
[Exclude]
|
||||
[IgnoreMember]
|
||||
public string FullPath => _fullPath ??= string.Join("|", ArchiveHashPath);
|
||||
}
|
||||
|
||||
[MessagePackObject]
|
||||
public class CreateBSA : Directive
|
||||
{
|
||||
public string TempID;
|
||||
public uint Type;
|
||||
[Key(3)]
|
||||
public string TempID { get; set; }
|
||||
[Key(4)]
|
||||
public ArchiveStateObject State { get; set; }
|
||||
[Key(5)]
|
||||
public List<FileStateObject> FileStates { get; set; }
|
||||
}
|
||||
|
||||
[MessagePackObject]
|
||||
public class PatchedFromArchive : FromArchive
|
||||
{
|
||||
[Key(4)]
|
||||
public Hash FromHash { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The file to apply to the source file to patch it
|
||||
/// </summary>
|
||||
public string PatchID;
|
||||
|
||||
[Exclude]
|
||||
public Hash FromHash;
|
||||
[Key(5)]
|
||||
public string PatchID { get; set; }
|
||||
}
|
||||
|
||||
[MessagePackObject]
|
||||
public class SourcePatch
|
||||
{
|
||||
public string RelativePath;
|
||||
public Hash Hash;
|
||||
[Key(0)]
|
||||
public Hash Hash { get; set; }
|
||||
[Key(1)]
|
||||
public string RelativePath { get; set; }
|
||||
}
|
||||
|
||||
[MessagePackObject]
|
||||
public class MergedPatch : Directive
|
||||
{
|
||||
public List<SourcePatch> Sources;
|
||||
public string PatchID;
|
||||
[Key(3)]
|
||||
public string PatchID { get; set; }
|
||||
[Key(4)]
|
||||
public List<SourcePatch> Sources { get; set; }
|
||||
}
|
||||
|
||||
[MessagePackObject]
|
||||
public class Archive
|
||||
{
|
||||
/// <summary>
|
||||
/// MurMur3 Hash of the archive
|
||||
/// </summary>
|
||||
[Key(0)]
|
||||
public Hash Hash { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Meta INI for the downloaded archive
|
||||
/// Meta INI for the downloaded archive
|
||||
/// </summary>
|
||||
[Key(1)]
|
||||
public string Meta { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Human friendly name of this archive
|
||||
/// </summary>
|
||||
[Key(2)]
|
||||
public string Name { get; set; }
|
||||
|
||||
[Key(3)]
|
||||
public long Size { get; set; }
|
||||
|
||||
[Key(4)]
|
||||
public AbstractDownloadState State { get; set; }
|
||||
}
|
||||
|
||||
@ -285,15 +330,4 @@ namespace Wabbajack.Lib
|
||||
{
|
||||
public string[] HashPath;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Data found inside a BSA file in an archive
|
||||
/// </summary>
|
||||
public class BSAIndexedEntry : IndexedEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// MurMur3 hash of the BSA this file comes from
|
||||
/// </summary>
|
||||
public string BSAHash;
|
||||
}
|
||||
}
|
||||
|
@ -3,13 +3,14 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Alphaleonis.Win32.Filesystem;
|
||||
using MessagePack;
|
||||
using Wabbajack.Lib.Validation;
|
||||
|
||||
namespace Wabbajack.Lib.Downloaders
|
||||
{
|
||||
public interface IMetaState
|
||||
{
|
||||
string URL { get; }
|
||||
Uri URL { get; }
|
||||
string Name { get; set; }
|
||||
string Author { get; set; }
|
||||
string Version { get; set; }
|
||||
@ -20,6 +21,22 @@ namespace Wabbajack.Lib.Downloaders
|
||||
Task<bool> LoadMetaData();
|
||||
}
|
||||
|
||||
[MessagePackObject]
|
||||
[Union(0, typeof(HTTPDownloader.State))]
|
||||
[Union(1, typeof(GameFileSourceDownloader.State))]
|
||||
[Union(2, typeof(GoogleDriveDownloader.State))]
|
||||
[Union(3, typeof(LoversLabDownloader.State))]
|
||||
[Union(4, typeof(ManualDownloader.State))]
|
||||
[Union(5, typeof(MediaFireDownloader.State))]
|
||||
[Union(6, typeof(MegaDownloader.State))]
|
||||
[Union(7, typeof(ModDBDownloader.State))]
|
||||
[Union(8, typeof(NexusDownloader.State))]
|
||||
[Union(9, typeof(SteamWorkshopDownloader.State))]
|
||||
[Union(10, typeof(VectorPlexusDownloader.State))]
|
||||
[Union(11, typeof(AFKModsDownloader.State))]
|
||||
[Union(12, typeof(TESAllianceDownloader.State))]
|
||||
[Union(13, typeof(BethesdaNetDownloader.State))]
|
||||
[Union(14, typeof(YouTubeDownloader.State))]
|
||||
public abstract class AbstractDownloadState
|
||||
{
|
||||
|
||||
@ -51,8 +68,10 @@ namespace Wabbajack.Lib.Downloaders
|
||||
TypeToName = NameToType.ToDictionary(k => k.Value, k => k.Key);
|
||||
}
|
||||
|
||||
[IgnoreMember]
|
||||
public abstract object[] PrimaryKey { get; }
|
||||
|
||||
[IgnoreMember]
|
||||
public string PrimaryKeyString
|
||||
{
|
||||
get
|
||||
|
@ -204,7 +204,7 @@ namespace Wabbajack.Lib.Downloaders
|
||||
}
|
||||
|
||||
// from IMetaState
|
||||
public string URL => $"{Site}/files/file/{FileName}";
|
||||
public Uri URL => new Uri($"{Site}/files/file/{FileName}");
|
||||
public string Name { get; set; }
|
||||
public string Author { get; set; }
|
||||
public string Version { get; set; }
|
||||
|
@ -2,13 +2,9 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Reflection.Emit;
|
||||
using System.Threading.Tasks;
|
||||
using Ceras;
|
||||
using SharpCompress.Common;
|
||||
using Wabbajack.Common;
|
||||
using Wabbajack.Lib.Exceptions;
|
||||
using Wabbajack.Lib.Validation;
|
||||
@ -53,14 +49,12 @@ namespace Wabbajack.Lib.Downloaders
|
||||
{
|
||||
}
|
||||
|
||||
[MemberConfig(TargetMember.All)]
|
||||
public class State : AbstractDownloadState
|
||||
{
|
||||
public string Url { get; set; }
|
||||
|
||||
public List<string> Headers { get; set; }
|
||||
|
||||
[Exclude]
|
||||
public Common.Http.Client Client { get; set; }
|
||||
|
||||
public override object[] PrimaryKey { get => new object[] {Url};}
|
||||
|
@ -5,6 +5,7 @@ using System.Linq;
|
||||
using System.Reactive.Linq;
|
||||
using System.Reactive.Subjects;
|
||||
using System.Threading.Tasks;
|
||||
using MessagePack;
|
||||
using Wabbajack.Common;
|
||||
using Wabbajack.Common.IO;
|
||||
using Wabbajack.Lib.Validation;
|
||||
@ -69,10 +70,14 @@ namespace Wabbajack.Lib.Downloaders
|
||||
public async Task Prepare()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
[MessagePackObject]
|
||||
public class State : AbstractDownloadState
|
||||
{
|
||||
[Key(0)]
|
||||
public string Url { get; set; }
|
||||
|
||||
[IgnoreMember]
|
||||
public override object[] PrimaryKey { get => new object[] {Url}; }
|
||||
|
||||
public override bool IsWhitelisted(ServerWhitelist whitelist)
|
||||
|
@ -1,19 +1,14 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Reactive;
|
||||
using System.Reactive.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using Ceras;
|
||||
using MongoDB.Bson.Serialization.Attributes;
|
||||
using ReactiveUI;
|
||||
using Wabbajack.Common;
|
||||
using Wabbajack.Common.StatusFeed.Errors;
|
||||
using Wabbajack.Lib.NexusApi;
|
||||
using Wabbajack.Lib.Validation;
|
||||
using Game = Wabbajack.Common.Game;
|
||||
|
||||
namespace Wabbajack.Lib.Downloaders
|
||||
{
|
||||
@ -126,7 +121,7 @@ namespace Wabbajack.Lib.Downloaders
|
||||
[BsonIgnoreExtraElements]
|
||||
public class State : AbstractDownloadState, IMetaState
|
||||
{
|
||||
public string URL => $"http://nexusmods.com/{NexusApiUtils.ConvertGameName(GameName)}/mods/{ModID}";
|
||||
public Uri URL => new Uri($"http://nexusmods.com/{NexusApiUtils.ConvertGameName(GameName)}/mods/{ModID}");
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
|
@ -313,7 +313,7 @@ namespace Wabbajack.Lib
|
||||
Description = ModListDescription ?? "",
|
||||
Readme = ModListReadme ?? "",
|
||||
Image = ModListImage ?? "",
|
||||
Website = ModListWebsite ?? ""
|
||||
Website = ModListWebsite != null ? new Uri(ModListWebsite) : null
|
||||
};
|
||||
|
||||
UpdateTracker.NextStep("Running Validation");
|
||||
@ -472,7 +472,8 @@ namespace Wabbajack.Lib
|
||||
Status($"Patching {entry.To}");
|
||||
var srcFile = byPath[string.Join("|", entry.ArchiveHashPath.Skip(1))];
|
||||
await using var srcStream = srcFile.OpenRead();
|
||||
await using var outputStream = IncludeFile(out entry.PatchID);
|
||||
await using var outputStream = IncludeFile(out var id);
|
||||
entry.PatchID = id;
|
||||
await using var destStream = LoadDataForTo(entry.To, absolutePaths);
|
||||
await Utils.CreatePatch(srcStream, srcFile.Hash, destStream, entry.Hash, outputStream);
|
||||
Info($"Patch size {outputStream.Length} for {entry.To}");
|
||||
|
@ -237,7 +237,7 @@ namespace Wabbajack.Lib
|
||||
Description = ModListDescription ?? "",
|
||||
Readme = ModListReadme ?? "",
|
||||
Image = ModListImage ?? "",
|
||||
Website = ModListWebsite ?? "",
|
||||
Website = ModListWebsite != null ? new Uri(ModListWebsite) : null,
|
||||
Archives = SelectedArchives.ToList(),
|
||||
ModManager = ModManager.Vortex,
|
||||
Directives = InstallDirectives,
|
||||
|
@ -12,9 +12,6 @@
|
||||
<PackageReference Include="CefSharp.OffScreen">
|
||||
<Version>79.1.350</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Ceras">
|
||||
<Version>4.1.7</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Fody">
|
||||
<Version>6.1.1</Version>
|
||||
</PackageReference>
|
||||
@ -30,6 +27,9 @@
|
||||
<PackageReference Include="MegaApiClient">
|
||||
<Version>1.7.1</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="MessagePackAnalyzer">
|
||||
<Version>2.1.90</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.CSharp">
|
||||
<Version>4.7.0</Version>
|
||||
</PackageReference>
|
||||
|
@ -54,7 +54,7 @@ namespace Wabbajack
|
||||
Metadata = metadata;
|
||||
Location = Path.Combine(Consts.ModListDownloadFolder, Metadata.Links.MachineURL + Consts.ModListExtension);
|
||||
IsBroken = metadata.ValidationSummary.HasFailures;
|
||||
OpenWebsiteCommand = ReactiveCommand.Create(() => Utils.OpenWebsite($"https://www.wabbajack.org/modlist/{Metadata.Links.MachineURL}"));
|
||||
OpenWebsiteCommand = ReactiveCommand.Create(() => Utils.OpenWebsite(new Uri($"https://www.wabbajack.org/modlist/{Metadata.Links.MachineURL}")));
|
||||
ExecuteCommand = ReactiveCommand.CreateFromObservable<Unit, Unit>(
|
||||
canExecute: this.WhenAny(x => x.IsBroken).Select(x => !x),
|
||||
execute: (unit) =>
|
||||
|
@ -324,7 +324,7 @@ namespace Wabbajack
|
||||
return Unit.Default;
|
||||
},
|
||||
canExecute: this.WhenAny(x => x.ModList.Website)
|
||||
.Select(x => x?.StartsWith("https://") ?? false)
|
||||
.Select(x => x != null)
|
||||
.ObserveOnGuiThread());
|
||||
|
||||
_progressTitle = this.WhenAnyValue(
|
||||
|
@ -20,7 +20,7 @@ namespace Wabbajack
|
||||
public string Readme => SourceModList?.Readme;
|
||||
public string Author => SourceModList?.Author;
|
||||
public string Description => SourceModList?.Description;
|
||||
public string Website => SourceModList?.Website;
|
||||
public Uri Website => SourceModList?.Website;
|
||||
public ModManager ModManager => SourceModList?.ModManager ?? ModManager.MO2;
|
||||
|
||||
// Image isn't exposed as a direct property, but as an observable.
|
||||
@ -96,7 +96,7 @@ namespace Wabbajack
|
||||
if (string.IsNullOrEmpty(Readme)) return;
|
||||
if (SourceModList.ReadmeIsWebsite)
|
||||
{
|
||||
Utils.OpenWebsite(Readme);
|
||||
Utils.OpenWebsite(new Uri(Readme));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -132,7 +132,7 @@ namespace Wabbajack
|
||||
.Select(x =>
|
||||
{
|
||||
var regex = new Regex("^(http|https):\\/\\/");
|
||||
return x != null && regex.Match(x).Success;
|
||||
return x != null && regex.Match(x.ToString()).Success;
|
||||
})
|
||||
.ObserveOnGuiThread());
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System.Diagnostics;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using Wabbajack.Common;
|
||||
@ -17,17 +18,17 @@ namespace Wabbajack
|
||||
|
||||
private void GitHub_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Utils.OpenWebsite("https://github.com/wabbajack-tools/wabbajack");
|
||||
Utils.OpenWebsite(new Uri("https://github.com/wabbajack-tools/wabbajack"));
|
||||
}
|
||||
|
||||
private void Discord_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Utils.OpenWebsite("https://discord.gg/wabbajack");
|
||||
Utils.OpenWebsite(new Uri("https://discord.gg/wabbajack"));
|
||||
}
|
||||
|
||||
private void Patreon_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Utils.OpenWebsite("https://www.patreon.com/user?u=11907933");
|
||||
Utils.OpenWebsite(new Uri("https://www.patreon.com/user?u=11907933"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user