Skip to content

Commit

Permalink
Installer support for 13; smaller bufixes; new binary patch
Browse files Browse the repository at this point in the history
  • Loading branch information
Nefaro committed Jan 10, 2023
1 parent aac9002 commit f184277
Show file tree
Hide file tree
Showing 19 changed files with 151 additions and 87 deletions.
2 changes: 1 addition & 1 deletion Gnoll Mods/Challenges/Challenges/Gui/ChallengesMenu.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ private void CenterTabControl()
this._tabControl.Top = (this.Height - this._tabControl.Height) / 2;
}

protected override void Dispose(bool disposing)
public override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (!disposing)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public ImportExportTrackedItemsDialog(Manager manager) : base(manager)
this.AddPage("Export", new ExportTrackedItemsDialog(this.Manager));
}

protected override void Dispose(bool disposing)
public override void Dispose(bool disposing)
{
base.Dispose(disposing);

Expand Down
2 changes: 1 addition & 1 deletion GnollModLoader/GnollModLoader/GnollMain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public class GnollMain

public const string MODS_DIR = "Gnoll Mods\\enabled";

private static bool debug = true;
private static bool debug = false;
public static bool Debug => debug;
public static string VERSION
{
Expand Down
6 changes: 3 additions & 3 deletions GnollModLoader/GnollModLoader/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
[assembly: AssemblyTitle("GnollModLoader")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyCompany("https://github.com/Nefaro/gnoll")]
[assembly: AssemblyProduct("GnollModLoader")]
[assembly: AssemblyCopyright("")]
[assembly: AssemblyTrademark("")]
Expand All @@ -32,5 +32,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.10.0.0")]
[assembly: AssemblyFileVersion("1.10.0.0")]
[assembly: AssemblyVersion("1.13.0.0")]
[assembly: AssemblyFileVersion("1.13.0.0")]
34 changes: 31 additions & 3 deletions Installer/InstallerCore/Action.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;

namespace InstallerCore
Expand All @@ -9,7 +10,7 @@ public abstract class Action

public void Execute()
{
_log.WriteLine(this.ToString());
_log.Log(this.ToString());
this.ExecuteImpl();
}

Expand Down Expand Up @@ -91,6 +92,7 @@ public override string ToString()

public class UninstallModKit : Action
{
private static readonly Logger _log = Logger.GetLogger;
public UninstallModKit(string catalogPath, string outputPath, string backupPath, string vanillaMd5, string patchVersion)
{
CatalogPath = catalogPath;
Expand All @@ -103,7 +105,14 @@ public UninstallModKit(string catalogPath, string outputPath, string backupPath,
protected override void ExecuteImpl()
{
// restore backup
File.Replace(BackupPath, OutputPath, destinationBackupFileName: null);
if (File.Exists(BackupPath))
{
File.Replace(BackupPath, OutputPath, destinationBackupFileName: null);
}
else
{
_log.Warn($"Trying to restore backup but file is missing: {BackupPath}");
}

// update catalog
var catalog = InstallDb.LoadOrEmpty(CatalogPath);
Expand Down Expand Up @@ -193,7 +202,7 @@ private void CopyFile(string source, string target, string backup)
}
else
{
_log.log($"Tasked with copying a file but source file is missing: {source}");
_log.Error($"Tasked with copying a file but source file is missing: {source}");
}
}

Expand All @@ -202,6 +211,25 @@ public override string ToString()
return $"$$ Install Mod Loader Dependency to {OutputPath}";
}

// For List.Contains
public override bool Equals(object obj)
{
return obj is InstallModLoaderDependency dependency &&
ModloaderPath == dependency.ModloaderPath &&
OutputPath == dependency.OutputPath &&
BackupPath == dependency.BackupPath &&
WithBackup == dependency.WithBackup;
}
public override int GetHashCode()
{
int hashCode = 971104037;
hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(ModloaderPath);
hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(OutputPath);
hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(BackupPath);
hashCode = hashCode * -1521134295 + WithBackup.GetHashCode();
return hashCode;
}

public string ModloaderPath { get; }
public string OutputPath { get; }
public string BackupPath { get; }
Expand Down
18 changes: 9 additions & 9 deletions Installer/InstallerCore/GamePatchDatabase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,16 @@ public class GamePatchDatabase
public GamePatchDatabase(string appFolder)
{
// The overall patch directory
_log.log($"App folder: {appFolder}");
_log.Log($"App folder: {appFolder}");
this._patchFolder = Path.Combine(appFolder, _patchFolderName);
_log.log($"Patch folder: {_patchFolder}");
_log.Log($"Patch folder: {_patchFolder}");
// Load the patch info
string jsonString = File.ReadAllText(Path.Combine(_patchFolder, _patchDatabaseName));
this._entries = JsonSerializer.Deserialize<GameEntry[]>(jsonString);
foreach(var ent in this._entries)
{
_log.log($"Entry: {ent.Name} - {ent.Md5sum}");
_log.log($"Entry patches: {ent.Patches.Count}");
_log.Log($"Entry: {ent.Name} - {ent.Md5sum}");
_log.Log($"Entry patches: {ent.Patches.Count}");
}
}

Expand Down Expand Up @@ -86,7 +86,7 @@ public PatchInstallable GetInstallablePatchIfAvailable(GameEntry gameEntry, stri

if ( !File.Exists(patchFile) )
{
_log.log($"Error: Cannot find patch file ( { patchFile })");
_log.Log($"Error: Cannot find patch file ( { patchFile })");
throw new FileNotFoundException($"Cannot find patch file '{Path.GetFileName(patchFile)}'. Is the database corrupt?");
}

Expand All @@ -99,7 +99,7 @@ public PatchInstallable GetInstallablePatchIfAvailable(GameEntry gameEntry, stri

public PatchEntry GetLatestPatch(GameEntry gameEntry)
{
_log.log($"Finding patch for: {gameEntry.Name} - {gameEntry.Md5sum}");
_log.Log($"Finding patch for: {gameEntry.Name} - {gameEntry.Md5sum}");
// try to find the latest patch
if (!string.IsNullOrEmpty(gameEntry.LatestPatch))
{
Expand All @@ -110,7 +110,7 @@ public PatchEntry GetLatestPatch(GameEntry gameEntry)
var patchFile = Path.Combine(this._patchFolder, patch.Filename);
if (File.Exists(patchFile))
{
_log.log($"Picked (latest) patch: {patch.VersionString}");
_log.Log($"Picked (latest) patch: {patch.VersionString}");
return patch;
}
}
Expand All @@ -123,10 +123,10 @@ public PatchEntry GetLatestPatch(GameEntry gameEntry)
gameEntry.Patches.Sort(
delegate (PatchEntry x, PatchEntry y) { return y.Version.CompareTo(x.Version); });

_log.log("Sorted patches:");
_log.Log("Sorted patches:");
foreach (var patch in gameEntry.Patches)
{
_log.log($" -- {patch.VersionString}");
_log.Log($" -- {patch.VersionString}");
}

return gameEntry.Patches[0];
Expand Down
75 changes: 50 additions & 25 deletions Installer/InstallerCore/InstallerCore.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.Eventing.Reader;
using System.IO;
using System.Linq;
using System.Security.Cryptography;

namespace InstallerCore
Expand Down Expand Up @@ -33,13 +35,17 @@ public class InstallerCore
{
private static readonly Logger _log = Logger.GetLogger;
private static readonly string _modLoaderFile = "GnollModLoader.dll";
private static readonly string _modLoaderDependency = "0Harmony.dll";
private static readonly List<String> _modLoaderDependencies = new List<string>()
{
"0Harmony.dll",
"Newtonsoft.Json.dll"
};
private static readonly string _modsDirectory = "Gnoll Mods";


public static ScanResult ScanGameInstall(string installDir, GamePatchDatabase gameDb)
{
_log.WriteLine($"About to scan game directory {installDir}");
_log.Log($"About to scan game directory {installDir}");

string gameExePath = Path.Combine(installDir, "Gnomoria.exe");
string backupExePath = Path.Combine(installDir, "Gnomoria.orig.exe");
Expand All @@ -48,14 +54,20 @@ public static ScanResult ScanGameInstall(string installDir, GamePatchDatabase ga
string modsSourcePath = Path.Combine(gameDb.PatchFolder, _modsDirectory);
string modsTargetPath = Path.Combine(installDir, _modsDirectory);

string dependencyTargetPath = Path.Combine(installDir, _modLoaderDependency);
string dependencySourcePath = Path.Combine(gameDb.PatchFolder, _modLoaderDependency);

List<Tuple<String, String>> dependencyPaths = new List<Tuple<String, String>>();
foreach (var dep in _modLoaderDependencies)
{
Tuple<String, String> item = new Tuple<String, String>(Path.Combine(gameDb.PatchFolder, dep), Path.Combine(installDir, dep));
if ( !dependencyPaths.Contains(item) )
{
dependencyPaths.Add(new Tuple<String, String>(Path.Combine(gameDb.PatchFolder, dep), Path.Combine(installDir, dep)));
}
}

// Load installation catalog (json file)

string catalogPath = Path.Combine(installDir, "gnoll-version.json");
_log.WriteLine($"{catalogPath} exists? => {File.Exists(catalogPath)}");
_log.Log($"{catalogPath} exists? => {File.Exists(catalogPath)}");
var catalog = InstallDb.LoadOrEmpty(catalogPath);

bool isExeModded = (catalog.DefaultRecord != null);
Expand All @@ -77,29 +89,28 @@ public static ScanResult ScanGameInstall(string installDir, GamePatchDatabase ga
{
var hash = md5.ComputeHash(stream);
vanillaGameMd5 = BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
_log.WriteLine($"Game not modded; calculated vanillaGameMd5 = {vanillaGameMd5}");
_log.Log($"Game not modded; calculated vanillaGameMd5 = {vanillaGameMd5}");
}
}
}
else
{
vanillaGameMd5 = catalog.DefaultRecord.VanillaMd5;
vanillaGamePath = backupExePath;
_log.WriteLine($"Game IS modded; reported vanillaGameMd5 = {vanillaGameMd5}");
_log.Log($"Game IS modded; reported vanillaGameMd5 = {vanillaGameMd5}");
}

GamePatchDatabase.GameEntry gameVersion = gameDb.GetGameEntryMd5Hash(vanillaGameMd5);

// Construct actions to offer
var actions = new List<Action>();
var installable = gameDb.GetInstallablePatchIfAvailable( gameVersion, vanillaGamePath);

// Check if current modkit version has been installed as stand-alone exe (trust the catalog)
bool isStandaloneInstallPresent = false;
bool isStandaloneUpToDate = false;
if (catalog.Standalone != null)
{
_log.WriteLine($"Detected stand-alone installation of build {catalog.Standalone.VersionString}");
_log.Log($"Detected stand-alone installation of build {catalog.Standalone.VersionString}");
isStandaloneInstallPresent = true;
if ( installable.PatchVersion.Equals(catalog.Standalone.VersionString) )
{
Expand All @@ -112,28 +123,31 @@ public static ScanResult ScanGameInstall(string installDir, GamePatchDatabase ga
{
if (installable != null)
{
_log.WriteLine($"Game not modded & patch available => propose InstallModKit");
_log.Log($"Game not modded & patch available => propose InstallModKit");
actions.Add(new InstallModKit(catalogPath, gameExePath, backupExePath, vanillaGameMd5, installable.PatchVersion, installable));
if ( File.Exists(modLoaderSourcePath) )
{
actions.Add(new InstallModLoaderDependency(modLoaderSourcePath, modLoaderTargetPath, true));
actions.Add(new InstallModLoaderDependency(dependencySourcePath, dependencyTargetPath, false));
actions.Add(new UninstallModLoaderDependency(modLoaderTargetPath));
actions.Add(new UninstallModLoaderDependency(dependencyTargetPath));
foreach(var pathTuple in dependencyPaths)
{
actions.Add(new InstallModLoaderDependency(pathTuple.Item1, pathTuple.Item2, false));
actions.Add(new UninstallModLoaderDependency(pathTuple.Item2));
}
}
else
{
_log.WriteLine($"Warning: Mod Loader not found; not installing");
_log.Warn($"Warning: Mod Loader not found; not installing");
}
}
else
{
_log.WriteLine($"Warning: no patch available for game version {vanillaGameMd5}");
_log.Warn($"Warning: no patch available for game version {vanillaGameMd5}");
}
}
else
{
_log.WriteLine($"Game modded => propose UninstallModKit");
_log.Log($"Game modded => propose UninstallModKit");
actions.Add(new UninstallModKit(catalogPath, gameExePath, backupExePath, vanillaGameMd5, moddedVersion));
}

Expand All @@ -146,30 +160,33 @@ public static ScanResult ScanGameInstall(string installDir, GamePatchDatabase ga
if (installable != null && standaloneUpToDateFilename != null)
{
string standalonePath = Path.Combine(installDir, standaloneUpToDateFilename);
_log.WriteLine($"Game not stand-alone modded & patch available => propose InstallStandalone");
_log.Log($"Game not stand-alone modded & patch available => propose InstallStandalone");
actions.Add(new InstallStandalone(catalogPath, standalonePath, vanillaGameMd5, installable.PatchVersion, installable));
if (File.Exists(modLoaderSourcePath))
{
actions.Add(new InstallModLoaderDependency(modLoaderSourcePath, modLoaderTargetPath, true));
actions.Add(new InstallModLoaderDependency(dependencySourcePath, dependencyTargetPath, false));
actions.Add(new UninstallModLoaderDependency(modLoaderTargetPath));
actions.Add(new UninstallModLoaderDependency(dependencyTargetPath));
addActionIfNotPresent(actions, new InstallModLoaderDependency(modLoaderSourcePath, modLoaderTargetPath, true));
addActionIfNotPresent(actions, new UninstallModLoaderDependency(modLoaderTargetPath));
foreach (var pathTuple in dependencyPaths)
{
addActionIfNotPresent(actions, new InstallModLoaderDependency(pathTuple.Item1, pathTuple.Item2, false));
addActionIfNotPresent(actions, new UninstallModLoaderDependency(pathTuple.Item2));
}
}
else
{
_log.WriteLine($"Warning: Mod Loader not found; not installing");
_log.Warn($"Warning: Mod Loader not found; not installing");
}
}
else
{
_log.WriteLine($"Warning: no patch available for game version {vanillaGameMd5}");
_log.Warn($"Warning: no patch available for game version {vanillaGameMd5}");
}
}
if(isStandaloneInstallPresent)
{

string standalonePath = Path.Combine(installDir, standaloneUpToDateFilename);
_log.WriteLine($"Game stand-alone modded => propose UninstallStandalone");
_log.Log($"Game stand-alone modded => propose UninstallStandalone");
actions.Add(new UninstallStandalone(catalogPath, standalonePath, vanillaGameMd5, standaloneOldFilename));
}
if ( Directory.Exists(modsSourcePath) )
Expand All @@ -179,10 +196,18 @@ public static ScanResult ScanGameInstall(string installDir, GamePatchDatabase ga
}
else
{
_log.WriteLine($"Warning: Mods not included in {modsSourcePath}");
_log.Warn($"Warning: Mods not included in {modsSourcePath}");
}
return new ScanResult(moddedVersion, gameVersion.Name, actions.ToArray(), patchAvailable: (installable != null),
standaloneOldFilename, standaloneUpToDateFilename,(installable!=null? installable.PatchVersion: null));
}

private static void addActionIfNotPresent(List<Action> actions, Action newAction)
{
if (!actions.Contains(newAction))
{
actions.Add(newAction);
}
}
}
}
10 changes: 1 addition & 9 deletions Installer/InstallerCore/InstallerCore.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -116,17 +116,9 @@
<None Include="app.config" />
<Compile Include="InstallerCore.cs" />
<None Include="packages.config" />
<None Include="Payloads\G1700_016e6239.xdelta" />
<None Include="Payloads\G1900_c9f6d4b9.xdelta" />
</ItemGroup>
<ItemGroup>
<None Include="Payloads\G1700_016e6239_full.exe" />
</ItemGroup>
<ItemGroup>
<None Include="Payloads\G0000_016e6239.exe" />
</ItemGroup>
<ItemGroup>
<None Include="Payloads\G0000_c9f6d4b9.exe" />
<Folder Include="Payloads\" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\packages\System.Text.Json.6.0.0\build\System.Text.Json.targets" Condition="Exists('..\packages\System.Text.Json.6.0.0\build\System.Text.Json.targets')" />
Expand Down
Loading

0 comments on commit f184277

Please sign in to comment.