mirror of
https://github.com/wabbajack-tools/wabbajack.git
synced 2024-08-30 18:42:17 +00:00
Merge branch 'master' into intervention-frontend
This commit is contained in:
commit
96c1fe6bff
BIN
Branding/PNGs/Wabba_Mouth_Small.png
Normal file
BIN
Branding/PNGs/Wabba_Mouth_Small.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 58 KiB |
@ -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);
|
||||
|
@ -677,4 +677,4 @@ namespace Wabbajack.Common
|
||||
return a < b ? b < c ? b : a < c ? c : a : b > c ? b : a > c ? c : a;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -665,6 +665,7 @@ namespace Wabbajack.Common
|
||||
|
||||
using (var f = File.OpenWrite(tmpName))
|
||||
{
|
||||
Status("Creating Patch");
|
||||
BSDiff.Create(a, b, f);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
||||
}
|
||||
};
|
||||
|
@ -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(),
|
||||
|
86
Wabbajack.Lib/Downloaders/GameFileSourceDownloader.cs
Normal file
86
Wabbajack.Lib/Downloaders/GameFileSourceDownloader.cs
Normal 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}";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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()
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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}");
|
||||
|
@ -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" />
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -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}"
|
||||
});
|
||||
|
@ -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}"
|
||||
});
|
||||
|
BIN
Wabbajack/Resources/Wabba_Mouth_Small.png
Normal file
BIN
Wabbajack/Resources/Wabba_Mouth_Small.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 58 KiB |
@ -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>
|
Loading…
Reference in New Issue
Block a user