Merge branch 'master' into intervention-frontend

This commit is contained in:
Justin Swanson 2019-12-10 21:49:20 -06:00
commit 96c1fe6bff
22 changed files with 195 additions and 25 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

View File

@ -73,7 +73,7 @@ namespace Compression.BSA.Test
var state = new NexusDownloader.State
{
ModID = info.Item2.ToString(),
GameName = GameRegistry.Games[info.Item1].NexusName,
GameName = info.Item1.MetaData().NexusName,
FileID = file.file_id.ToString()
};
state.Download(src);

View File

@ -677,4 +677,4 @@ namespace Wabbajack.Common
return a < b ? b < c ? b : a < c ? c : a : b > c ? b : a > c ? c : a;
}
}
}
}

View File

@ -67,12 +67,13 @@ namespace Wabbajack.Common
public List<string> RequiredFiles { get; internal set; }
public bool Disabled { get; internal set; }
public string GameLocation(bool steam)
public string GameLocation()
{
if (Consts.TestMode)
return Directory.GetCurrentDirectory();
return steam ? SteamHandler.Instance.Games.FirstOrDefault(g => g.Game == Game)?.InstallDir : GOGHandler.Instance.Games.FirstOrDefault(g => g.Game == Game)?.Path;
return SteamHandler.Instance.Games.FirstOrDefault(g => g.Game == Game)?.InstallDir ??
GOGHandler.Instance.Games.FirstOrDefault(g => g.Game == Game)?.Path;
}
}

View File

@ -95,6 +95,9 @@ namespace Wabbajack.Common
paths.Add(s);
});
// Default path in the Steam folder isn't in the configs
paths.Add(Path.Combine(SteamPath, "steamapps"));
InstallFolders = paths;
}

View File

@ -665,6 +665,7 @@ namespace Wabbajack.Common
using (var f = File.OpenWrite(tmpName))
{
Status("Creating Patch");
BSDiff.Create(a, b, f);
}

View File

@ -24,7 +24,7 @@ namespace Wabbajack.Lib
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(LoversLabDownloader.State), typeof(GameFileSourceDownloader.State)
}
};

View File

@ -9,6 +9,7 @@ namespace Wabbajack.Lib.Downloaders
{
public static readonly List<IDownloader> Downloaders = new List<IDownloader>()
{
new GameFileSourceDownloader(),
new MegaDownloader(),
new DropboxDownloader(),
new GoogleDriveDownloader(),

View File

@ -0,0 +1,86 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Alphaleonis.Win32.Filesystem;
using Wabbajack.Common;
using Wabbajack.Lib.Validation;
using File = Alphaleonis.Win32.Filesystem.File;
using Game = Wabbajack.Common.Game;
namespace Wabbajack.Lib.Downloaders
{
public class GameFileSourceDownloader : IDownloader
{
public AbstractDownloadState GetDownloaderState(dynamic archiveINI)
{
var gameName = (string)archiveINI?.General?.gameName;
var gameFile = (string)archiveINI?.General?.gameFile;
if (gameFile == null || gameFile == null)
return null;
var game = GameRegistry.GetByMO2ArchiveName(gameName);
if (game == null) return null;
var path = game.GameLocation();
var filePath = Path.Combine(path, gameFile);
if (!File.Exists(filePath))
return null;
var hash = filePath.FileHashCached();
return new State
{
Game = GameRegistry.GetByMO2ArchiveName(gameName).Game,
GameFile = gameFile,
Hash = hash,
};
}
public void Prepare()
{
}
public class State : AbstractDownloadState
{
public Game Game { get; set; }
public string GameFile { get; set; }
public string Hash { get; set; }
internal string SourcePath => Path.Combine(Game.MetaData().GameLocation(), GameFile);
public override bool IsWhitelisted(ServerWhitelist whitelist)
{
return true;
}
public override void Download(Archive a, string destination)
{
using(var src = File.OpenRead(SourcePath))
using (var dest = File.OpenWrite(destination))
{
var size = new FileInfo(SourcePath).Length;
src.CopyToWithStatus(size, dest, "Copying from Game folder");
}
}
public override bool Verify()
{
return File.Exists(SourcePath) && SourcePath.FileHashCached() == Hash;
}
public override IDownloader GetDownloader()
{
return DownloadDispatcher.GetInstance<GameFileSourceDownloader>();
}
public override string GetReportEntry(Archive a)
{
return $"* Game File {Game} - {GameFile}";
}
}
}
}

View File

@ -5,12 +5,15 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Alphaleonis.Win32.Filesystem;
using Wabbajack.Common;
using Wabbajack.Lib.CompilationSteps;
using Wabbajack.Lib.NexusApi;
using Wabbajack.Lib.Validation;
using Directory = Alphaleonis.Win32.Filesystem.Directory;
using File = Alphaleonis.Win32.Filesystem.File;
using FileInfo = Alphaleonis.Win32.Filesystem.FileInfo;
using Game = Wabbajack.Common.Game;
using Path = Alphaleonis.Win32.Filesystem.Path;
namespace Wabbajack.Lib
@ -29,6 +32,8 @@ namespace Wabbajack.Lib
public override string GamePath { get; }
public GameMetaData CompilingGame { get; set; }
public override string ModListOutputFolder => "output_folder";
public override string ModListOutputFile { get; }
@ -38,6 +43,8 @@ namespace Wabbajack.Lib
MO2Folder = mo2Folder;
MO2Profile = mo2Profile;
MO2Ini = Path.Combine(MO2Folder, "ModOrganizer.ini").LoadIniFile();
var mo2game = (string)MO2Ini.General.gameName;
CompilingGame = GameRegistry.Games.First(g => g.Value.MO2Name == mo2game).Value;
GamePath = ((string)MO2Ini.General.gamePath).Replace("\\\\", "\\");
ModListOutputFile = outputFile;
}
@ -72,7 +79,7 @@ namespace Wabbajack.Lib
protected override bool _Begin()
{
ConfigureProcessor(16);
ConfigureProcessor(18);
UpdateTracker.Reset();
UpdateTracker.NextStep("Gathering information");
Info("Looking for other profiles");
@ -116,6 +123,13 @@ namespace Wabbajack.Lib
if (Directory.Exists(ModListOutputFolder))
Utils.DeleteDirectory(ModListOutputFolder);
UpdateTracker.NextStep("Inferring metas for game file downloads");
InferMetas();
UpdateTracker.NextStep("Reindexing downloads after meta inferring");
VFS.AddRoot(MO2DownloadsFolder);
VFS.WriteToFile(_vfsCacheName);
UpdateTracker.NextStep("Finding Install Files");
Directory.CreateDirectory(ModListOutputFolder);
@ -244,7 +258,7 @@ namespace Wabbajack.Lib
ModList = new ModList
{
GameType = GameRegistry.Games.Values.First(f => f.MO2Name == MO2Ini.General.gameName).Game,
GameType = CompilingGame.Game,
WabbajackVersion = WabbajackVersion,
Archives = SelectedArchives.ToList(),
ModManager = ModManager.MO2,
@ -275,6 +289,41 @@ namespace Wabbajack.Lib
return true;
}
private void InferMetas()
{
var to_find = Directory.EnumerateFiles(MO2DownloadsFolder)
.Where(f => !f.EndsWith(".meta") && !f.EndsWith(Consts.HashFileExtension))
.Where(f => !File.Exists(f + ".meta"))
.ToList();
if (to_find.Count == 0) return;
var games = new[]{CompilingGame}.Concat(GameRegistry.Games.Values.Where(g => g != CompilingGame));
var game_files = games
.Where(g => g.GameLocation() != null)
.SelectMany(game => Directory.EnumerateFiles(game.GameLocation(), "*", DirectoryEnumerationOptions.Recursive).Select(name => (game, name)))
.GroupBy(f => (Path.GetFileName(f.name), new FileInfo(f.name).Length))
.ToDictionary(f => f.Key);
to_find.PMap(Queue, f =>
{
var vf = VFS.Index.ByFullPath[f];
if (!game_files.TryGetValue((Path.GetFileName(f), vf.Size), out var found))
return;
var (game, name) = found.FirstOrDefault(ff => ff.name.FileHash() == vf.Hash);
if (name == null)
return;
File.WriteAllLines(f+".meta", new[]
{
"[General]",
$"gameName={game.MO2ArchiveName}",
$"gameFile={name.RelativeTo(game.GameLocation()).Replace("\\", "/")}"
});
});
}
private void IncludeArchiveMetadata()

View File

@ -37,10 +37,10 @@ namespace Wabbajack.Lib
protected override bool _Begin()
{
ConfigureProcessor(18, RecommendQueueSize());
var game = GameRegistry.Games[ModList.GameType];
var game = ModList.GameType.MetaData();
if (GameFolder == null)
GameFolder = game.GameLocation(SteamHandler.Instance.Games.Any(g => g.Game == game.Game));
GameFolder = game.GameLocation();
if (GameFolder == null)
{

View File

@ -322,13 +322,13 @@ namespace Wabbajack.Lib.NexusApi
public GetModFilesResponse GetModFiles(Game game, int modid)
{
var url = $"https://api.nexusmods.com/v1/games/{GameRegistry.Games[game].NexusName}/mods/{modid}/files.json";
var url = $"https://api.nexusmods.com/v1/games/{game.MetaData().NexusName}/mods/{modid}/files.json";
return GetCached<GetModFilesResponse>(url);
}
public List<MD5Response> GetModInfoFromMD5(Game game, string md5Hash)
{
var url = $"https://api.nexusmods.com/v1/games/{GameRegistry.Games[game].NexusName}/mods/md5_search/{md5Hash}.json";
var url = $"https://api.nexusmods.com/v1/games/{game.MetaData().NexusName}/mods/md5_search/{md5Hash}.json";
return Get<List<MD5Response>>(url);
}

View File

@ -14,7 +14,7 @@ namespace Wabbajack.Lib.NexusApi
public static string GetModURL(Game game, string argModId)
{
return $"https://nexusmods.com/{GameRegistry.Games[game].NexusName}/mods/{argModId}";
return $"https://nexusmods.com/{game.MetaData().NexusName}/mods/{argModId}";
}
public static string FixupSummary(string argSummary)

View File

@ -140,7 +140,7 @@ namespace Wabbajack.Lib.Validation
}
});
var nexus = NexusApi.NexusApiUtils.ConvertGameName(GameRegistry.Games[modlist.GameType].NexusName);
var nexus = NexusApi.NexusApiUtils.ConvertGameName(modlist.GameType.MetaData().NexusName);
modlist.Archives
.Where(a => a.State is NexusDownloader.State)

View File

@ -50,7 +50,7 @@ namespace Wabbajack.Lib
Game = game;
GamePath = gamePath;
GameName = GameRegistry.Games[game].NexusName;
GameName = game.MetaData().NexusName;
VortexFolder = vortexFolder;
DownloadsFolder = downloadsFolder;
StagingFolder = stagingFolder;
@ -261,7 +261,7 @@ namespace Wabbajack.Lib
Directory.EnumerateFiles(GamePath, "vortex.deployment.json", SearchOption.AllDirectories)
.Where(File.Exists)
.Do(f => deploymentFile = f);
var currentGame = GameRegistry.Games[Game];
var currentGame = Game.MetaData();
if (currentGame.AdditionalFolders != null && currentGame.AdditionalFolders.Count != 0)
currentGame.AdditionalFolders.Do(f => Directory.EnumerateFiles(f, "vortex.deployment.json", SearchOption.AllDirectories)
.Where(File.Exists)
@ -300,7 +300,7 @@ namespace Wabbajack.Lib
/// </summary>
private void AddExternalFolder()
{
var currentGame = GameRegistry.Games[Game];
var currentGame = Game.MetaData();
if (currentGame.AdditionalFolders == null || currentGame.AdditionalFolders.Count == 0) return;
currentGame.AdditionalFolders.Do(f =>
{
@ -472,13 +472,13 @@ namespace Wabbajack.Lib
public static string RetrieveDownloadLocation(Game game, string vortexFolderPath = null)
{
vortexFolderPath = vortexFolderPath ?? TypicalVortexFolder();
return Path.Combine(vortexFolderPath, "downloads", GameRegistry.Games[game].NexusName);
return Path.Combine(vortexFolderPath, "downloads", game.MetaData().NexusName);
}
public static string RetrieveStagingLocation(Game game, string vortexFolderPath = null)
{
vortexFolderPath = vortexFolderPath ?? TypicalVortexFolder();
var gameName = GameRegistry.Games[game].NexusName;
var gameName = game.MetaData().NexusName;
return Path.Combine(vortexFolderPath, gameName, "mods");
}
@ -508,7 +508,7 @@ namespace Wabbajack.Lib
public static bool IsActiveVortexGame(Game g)
{
return GameRegistry.Games[g].SupportedModManager == ModManager.Vortex && !GameRegistry.Games[g].Disabled;
return g.MetaData().SupportedModManager == ModManager.Vortex && !GameRegistry.Games[g].Disabled;
}
}

View File

@ -29,7 +29,7 @@ namespace Wabbajack.Lib
IgnoreMissingFiles = true;
#endif
GameInfo = GameRegistry.Games[ModList.GameType];
GameInfo = ModList.GameType.MetaData();
}
protected override bool _Begin()
@ -85,7 +85,7 @@ namespace Wabbajack.Lib
var manualFilesDir = Path.Combine(OutputFolder, Consts.ManualGameFilesDir);
var gameFolder = GameInfo.GameLocation(SteamHandler.Instance.Games.Any(g => g.Game == GameInfo.Game));
var gameFolder = GameInfo.GameLocation();
Info($"Copying files from {manualFilesDir} " +
$"to the game folder at {gameFolder}");

View File

@ -116,6 +116,7 @@
<Compile Include="CompilationSteps\IStackStep.cs" />
<Compile Include="CompilationSteps\PatchStockESMs.cs" />
<Compile Include="CompilationSteps\Serialization.cs" />
<Compile Include="Downloaders\GameFileSourceDownloader.cs" />
<Compile Include="Downloaders\LoversLabDownloader.cs" />
<Compile Include="Downloaders\SteamWorkshopDownloader.cs" />
<Compile Include="LibCefHelpers\Init.cs" />

View File

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using Alphaleonis.Win32.Filesystem;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Wabbajack.Common;
using Wabbajack.Common.StatusFeed;
@ -11,6 +12,7 @@ using Wabbajack.Lib.LibCefHelpers;
using Wabbajack.Lib.NexusApi;
using Wabbajack.Lib.Validation;
using File = Alphaleonis.Win32.Filesystem.File;
using Game = Wabbajack.Common.Game;
namespace Wabbajack.Test
{
@ -298,8 +300,32 @@ namespace Wabbajack.Test
Assert.AreEqual("eSIyd+KOG3s=", Utils.FileHash(filename));
Assert.AreEqual(File.ReadAllText(filename), "Cheese for Everyone!");
}
[TestMethod]
public void GameFileSourceDownload()
{
DownloadDispatcher.GetInstance<LoversLabDownloader>().Prepare();
var ini = $@"[General]
gameName={Game.SkyrimSpecialEdition.MetaData().MO2ArchiveName}
gameFile=Data/Update.esm";
var state = (AbstractDownloadState)DownloadDispatcher.ResolveArchive(ini.LoadIniString());
Assert.IsNotNull(state);
var converted = state.ViaJSON();
Assert.IsTrue(converted.Verify());
var filename = Guid.NewGuid().ToString();
Assert.IsTrue(converted.IsWhitelisted(new ServerWhitelist { AllowedPrefixes = new List<string>() }));
converted.Download(new Archive { Name = "Update.esm" }, filename);
Assert.AreEqual("/DLG/LjdGXI=", Utils.FileHash(filename));
CollectionAssert.AreEqual(File.ReadAllBytes(Path.Combine(Game.SkyrimSpecialEdition.MetaData().GameLocation(), "Data/Update.esm")), File.ReadAllBytes(filename));
}
}

View File

@ -112,7 +112,7 @@ namespace Wabbajack.Test
new List<string>
{
"[General]",
$"gameName={GameRegistry.Games[game].MO2ArchiveName}",
$"gameName={game.MetaData().MO2ArchiveName}",
$"modID={modid}",
$"fileID={file.file_id}"
});

View File

@ -46,7 +46,7 @@ namespace Wabbajack.Test
File.WriteAllLines(Path.Combine(MO2Folder, "ModOrganizer.ini"), new []
{
"[General]",
$"gameName={GameRegistry.Games[Game].MO2Name}",
$"gameName={Game.MetaData().MO2Name}",
$"gamePath={GameFolder.Replace("\\", "\\\\")}",
$"download_directory={DownloadsFolder}"
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

View File

@ -544,6 +544,8 @@
<ItemGroup>
<Resource Include="Resources\Wabba_Ded.png" />
</ItemGroup>
<ItemGroup />
<ItemGroup>
<SplashScreen Include="Resources\Wabba_Mouth_Small.png" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>