Skip to content

Instantly share code, notes, and snippets.

@cake-pie
Created April 18, 2019 16:02
Show Gist options
  • Save cake-pie/0405eccac9c9d535be8d2a9c8651bfd2 to your computer and use it in GitHub Desktop.
Save cake-pie/0405eccac9c9d535be8d2a9c8651bfd2 to your computer and use it in GitHub Desktop.
Multiple copies of Harmony in GameData of Kerbal Space Program

These are test results for what happens in various cases when multiple copies of Harmony exist in GameData of Kerbal Space Program, e.g. caused by multiple mods bundling their own copy.

One question relates to which copy (or copies) get loaded and used by the respective mods that bundled them. This may affect the choice between whether individual mods should bundle their own copy of Harmony, or list it as a dependency to be obtained separately. See: KSP-CKAN/NetKAN#7131

It was also unclear whether having multiple copies in KSP in this manner might lead to problems. Per Harmony#102 while it worked without a hitch in RimWorld, it did cause issues for Cities: Skylines.


Methodology

Three slightly modified versions of HarmonyUser.cs are made and compiled, differing in only the class name, AssemblyTitle and the assembly name (*.dll file name). These are packaged as three different "mods" with slightly different layouts:

TestA
GameData
+ TestA
  + 0Harmony-A.dll
  + harmonytestA.dll
TestB
GameData
+ TestB
  + Harmony
  | + 0Harmony-B.dll
  + harmonytestB.dll
TestC
GameData
+ 0Harmony
| + 0Harmony-C.dll
+ TestC
  + harmonytestC.dll

All three mods are installed at the same time on a copy of KSP 1.7.0.
However, the actual versions of Harmony bundled with each mod varies.
We test three different scenarios:

Scenario A

0Harmony-A.dll is v1.2.0.1 the other two are v1.1.1.0 / v1.1.1

Scenario B

0Harmony-B.dll is v1.2.0.1 the other two are v1.1.1.0 / v1.1.1

Scenario c

0Harmony-C.dll is v1.2.0.1 the other two are v1.1.1.0 / v1.1.1


Results

Logs ScenarioA.log, ScenarioB.log & ScenarioC.log below.

The newest version of Harmony is always used, and all mods use the same copy.

using System.Reflection;
using UnityEngine;
using Harmony;
namespace harmonytest
{
[KSPAddon(KSPAddon.Startup.MainMenu, true)]
public class HarmonyUser : MonoBehaviour
{
internal bool firstrun = true;
private void Awake()
{
if (firstrun)
{
Assembly harmonyAssy = typeof(HarmonyInstance).Assembly;
firstrun = false;
Debug.LogFormat("HarmonyUser at {0} obtained Harmony {1} from {2}", new object[] {
this.GetType().Assembly.Location,
harmonyAssy.GetName().Version.ToString(),
harmonyAssy.Location
});
}
Destroy(gameObject);
}
}
}
// 0Harmony-A.dll is v1.2.0.1
// the other two are v1.1.1.0 / v1.1.1
...
[LOG 08:14:41.868] Load(Assembly): 0Harmony/0Harmony-C
[LOG 08:14:41.871] AssemblyLoader: Loading assembly at D:\ksp\1.7.0\KSP_win64-1.7.0-harmonytest\GameData\0Harmony\0Harmony-C.dll
[LOG 08:14:41.937] Load(Assembly): TestA/0Harmony-A
[LOG 08:14:41.937] AssemblyLoader: Loading assembly at D:\ksp\1.7.0\KSP_win64-1.7.0-harmonytest\GameData\TestA\0Harmony-A.dll
[LOG 08:14:41.940] Load(Assembly): TestA/harmonytestA
[LOG 08:14:41.940] AssemblyLoader: Loading assembly at D:\ksp\1.7.0\KSP_win64-1.7.0-harmonytest\GameData\TestA\harmonytestA.dll
[LOG 08:14:41.942] Load(Assembly): TestB/harmonytestB
[LOG 08:14:41.943] AssemblyLoader: Loading assembly at D:\ksp\1.7.0\KSP_win64-1.7.0-harmonytest\GameData\TestB\harmonytestB.dll
[LOG 08:14:41.945] Load(Assembly): TestB/Harmony/0Harmony-B
[LOG 08:14:41.945] AssemblyLoader: Loading assembly at D:\ksp\1.7.0\KSP_win64-1.7.0-harmonytest\GameData\TestB\Harmony\0Harmony-B.dll
[LOG 08:14:41.948] Load(Assembly): TestC/harmonytestC
[LOG 08:14:41.948] AssemblyLoader: Loading assembly at D:\ksp\1.7.0\KSP_win64-1.7.0-harmonytest\GameData\TestC\harmonytestC.dll
[LOG 08:14:41.954] AssemblyLoader: Loading assemblies
...
************************************************************************
Environment Info
Win32NT 7FFFFFFFFFFFFFFF Args: KSP_x64.exe
Mod DLLs found:
Stock assembly: Assembly-CSharp v0.0.0.0
0Harmony v1.1.1.0 / v1.1.1
0Harmony v1.2.0.1
harmonytestA v1.0.0.0
harmonytestB v1.0.0.0
0Harmony v1.1.1.0 / v1.1.1
harmonytestC v1.0.0.0
Folders and files in GameData:
0Harmony
Stock folder: Squad
TestA
TestB
TestC
************************************************************************
...
[LOG 08:15:17.595] [UIMasterController]: HideUI
[LOG 08:15:17.604] [HighLogic]: =========================== Scene Change : From LOADING to MAINMENU =====================
[LOG 08:15:18.380] [AddonLoader]: Instantiating addon 'ContractDefs' from assembly 'KSP'
[WRN 08:15:18.409] Contract Log: ContractDefs cannot load Sentinel.ExceptionalDeviation , it is not in the node. Initializing with default of 3!
[LOG 08:15:18.415] [AddonLoader]: Instantiating addon 'HarmonyUserA' from assembly 'harmonytestA'
[LOG 08:15:18.417] HarmonyUser at D:\ksp\1.7.0\KSP_win64-1.7.0-harmonytest\GameData\TestA\harmonytestA.dll obtained Harmony 1.2.0.1 from D:\ksp\1.7.0\KSP_win64-1.7.0-harmonytest\GameData\TestA\0Harmony-A.dll
[LOG 08:15:18.417] [AddonLoader]: Instantiating addon 'HarmonyUserB' from assembly 'harmonytestB'
[LOG 08:15:18.419] HarmonyUser at D:\ksp\1.7.0\KSP_win64-1.7.0-harmonytest\GameData\TestB\harmonytestB.dll obtained Harmony 1.2.0.1 from D:\ksp\1.7.0\KSP_win64-1.7.0-harmonytest\GameData\TestA\0Harmony-A.dll
[LOG 08:15:18.419] [AddonLoader]: Instantiating addon 'HarmonyUserC' from assembly 'harmonytestC'
[LOG 08:15:18.420] HarmonyUser at D:\ksp\1.7.0\KSP_win64-1.7.0-harmonytest\GameData\TestC\harmonytestC.dll obtained Harmony 1.2.0.1 from D:\ksp\1.7.0\KSP_win64-1.7.0-harmonytest\GameData\TestA\0Harmony-A.dll
[LOG 08:15:18.426] [UIMasterController]: ShowUI
// 0Harmony-B.dll is v1.2.0.1
// the other two are v1.1.1.0 / v1.1.1
...
[LOG 08:12:01.813] Load(Assembly): 0Harmony/0Harmony-C
[LOG 08:12:01.816] AssemblyLoader: Loading assembly at D:\ksp\1.7.0\KSP_win64-1.7.0-harmonytest\GameData\0Harmony\0Harmony-C.dll
[LOG 08:12:01.884] Load(Assembly): TestA/0Harmony-A
[LOG 08:12:01.884] AssemblyLoader: Loading assembly at D:\ksp\1.7.0\KSP_win64-1.7.0-harmonytest\GameData\TestA\0Harmony-A.dll
[LOG 08:12:01.888] Load(Assembly): TestA/harmonytestA
[LOG 08:12:01.888] AssemblyLoader: Loading assembly at D:\ksp\1.7.0\KSP_win64-1.7.0-harmonytest\GameData\TestA\harmonytestA.dll
[LOG 08:12:01.890] Load(Assembly): TestB/harmonytestB
[LOG 08:12:01.890] AssemblyLoader: Loading assembly at D:\ksp\1.7.0\KSP_win64-1.7.0-harmonytest\GameData\TestB\harmonytestB.dll
[LOG 08:12:01.892] Load(Assembly): TestB/Harmony/0Harmony-B
[LOG 08:12:01.893] AssemblyLoader: Loading assembly at D:\ksp\1.7.0\KSP_win64-1.7.0-harmonytest\GameData\TestB\Harmony\0Harmony-B.dll
[LOG 08:12:01.895] Load(Assembly): TestC/harmonytestC
[LOG 08:12:01.896] AssemblyLoader: Loading assembly at D:\ksp\1.7.0\KSP_win64-1.7.0-harmonytest\GameData\TestC\harmonytestC.dll
[LOG 08:12:01.902] AssemblyLoader: Loading assemblies
...
************************************************************************
Environment Info
Win32NT 7FFFFFFFFFFFFFFF Args: KSP_x64.exe
Mod DLLs found:
Stock assembly: Assembly-CSharp v0.0.0.0
0Harmony v1.1.1.0 / v1.1.1
0Harmony v1.1.1.0 / v1.1.1
harmonytestA v1.0.0.0
harmonytestB v1.0.0.0
0Harmony v1.2.0.1
harmonytestC v1.0.0.0
Folders and files in GameData:
0Harmony
Stock folder: Squad
TestA
TestB
TestC
************************************************************************
...
[LOG 08:12:34.723] [UIMasterController]: HideUI
[LOG 08:12:34.732] [HighLogic]: =========================== Scene Change : From LOADING to MAINMENU =====================
[LOG 08:12:35.502] [AddonLoader]: Instantiating addon 'ContractDefs' from assembly 'KSP'
[WRN 08:12:35.531] Contract Log: ContractDefs cannot load Sentinel.ExceptionalDeviation , it is not in the node. Initializing with default of 3!
[LOG 08:12:35.537] [AddonLoader]: Instantiating addon 'HarmonyUserA' from assembly 'harmonytestA'
[LOG 08:12:35.539] HarmonyUser at D:\ksp\1.7.0\KSP_win64-1.7.0-harmonytest\GameData\TestA\harmonytestA.dll obtained Harmony 1.2.0.1 from D:\ksp\1.7.0\KSP_win64-1.7.0-harmonytest\GameData\TestB\Harmony\0Harmony-B.dll
[LOG 08:12:35.539] [AddonLoader]: Instantiating addon 'HarmonyUserB' from assembly 'harmonytestB'
[LOG 08:12:35.540] HarmonyUser at D:\ksp\1.7.0\KSP_win64-1.7.0-harmonytest\GameData\TestB\harmonytestB.dll obtained Harmony 1.2.0.1 from D:\ksp\1.7.0\KSP_win64-1.7.0-harmonytest\GameData\TestB\Harmony\0Harmony-B.dll
[LOG 08:12:35.541] [AddonLoader]: Instantiating addon 'HarmonyUserC' from assembly 'harmonytestC'
[LOG 08:12:35.542] HarmonyUser at D:\ksp\1.7.0\KSP_win64-1.7.0-harmonytest\GameData\TestC\harmonytestC.dll obtained Harmony 1.2.0.1 from D:\ksp\1.7.0\KSP_win64-1.7.0-harmonytest\GameData\TestB\Harmony\0Harmony-B.dll
[LOG 08:12:35.548] [UIMasterController]: ShowUI
// 0Harmony-C.dll is v1.2.0.1
// the other two are v1.1.1.0 / v1.1.1
...
[LOG 08:16:51.280] Load(Assembly): 0Harmony/0Harmony-C
[LOG 08:16:51.283] AssemblyLoader: Loading assembly at D:\ksp\1.7.0\KSP_win64-1.7.0-harmonytest\GameData\0Harmony\0Harmony-C.dll
[LOG 08:16:51.349] Load(Assembly): TestA/0Harmony-A
[LOG 08:16:51.350] AssemblyLoader: Loading assembly at D:\ksp\1.7.0\KSP_win64-1.7.0-harmonytest\GameData\TestA\0Harmony-A.dll
[LOG 08:16:51.353] Load(Assembly): TestA/harmonytestA
[LOG 08:16:51.353] AssemblyLoader: Loading assembly at D:\ksp\1.7.0\KSP_win64-1.7.0-harmonytest\GameData\TestA\harmonytestA.dll
[LOG 08:16:51.355] Load(Assembly): TestB/harmonytestB
[LOG 08:16:51.355] AssemblyLoader: Loading assembly at D:\ksp\1.7.0\KSP_win64-1.7.0-harmonytest\GameData\TestB\harmonytestB.dll
[LOG 08:16:51.357] Load(Assembly): TestB/Harmony/0Harmony-B
[LOG 08:16:51.358] AssemblyLoader: Loading assembly at D:\ksp\1.7.0\KSP_win64-1.7.0-harmonytest\GameData\TestB\Harmony\0Harmony-B.dll
[LOG 08:16:51.360] Load(Assembly): TestC/harmonytestC
[LOG 08:16:51.360] AssemblyLoader: Loading assembly at D:\ksp\1.7.0\KSP_win64-1.7.0-harmonytest\GameData\TestC\harmonytestC.dll
[LOG 08:16:51.367] AssemblyLoader: Loading assemblies
...
************************************************************************
Environment Info
Win32NT 7FFFFFFFFFFFFFFF Args: KSP_x64.exe
Mod DLLs found:
Stock assembly: Assembly-CSharp v0.0.0.0
0Harmony v1.2.0.1
0Harmony v1.1.1.0 / v1.1.1
harmonytestA v1.0.0.0
harmonytestB v1.0.0.0
0Harmony v1.1.1.0 / v1.1.1
harmonytestC v1.0.0.0
Folders and files in GameData:
0Harmony
Stock folder: Squad
TestA
TestB
TestC
************************************************************************
...
[LOG 08:17:21.789] [UIMasterController]: HideUI
[LOG 08:17:21.797] [HighLogic]: =========================== Scene Change : From LOADING to MAINMENU =====================
[LOG 08:17:22.378] [AddonLoader]: Instantiating addon 'ContractDefs' from assembly 'KSP'
[WRN 08:17:22.398] Contract Log: ContractDefs cannot load Sentinel.ExceptionalDeviation , it is not in the node. Initializing with default of 3!
[LOG 08:17:22.402] [AddonLoader]: Instantiating addon 'HarmonyUserA' from assembly 'harmonytestA'
[LOG 08:17:22.404] HarmonyUser at D:\ksp\1.7.0\KSP_win64-1.7.0-harmonytest\GameData\TestA\harmonytestA.dll obtained Harmony 1.2.0.1 from D:\ksp\1.7.0\KSP_win64-1.7.0-harmonytest\GameData\0Harmony\0Harmony-C.dll
[LOG 08:17:22.404] [AddonLoader]: Instantiating addon 'HarmonyUserB' from assembly 'harmonytestB'
[LOG 08:17:22.405] HarmonyUser at D:\ksp\1.7.0\KSP_win64-1.7.0-harmonytest\GameData\TestB\harmonytestB.dll obtained Harmony 1.2.0.1 from D:\ksp\1.7.0\KSP_win64-1.7.0-harmonytest\GameData\0Harmony\0Harmony-C.dll
[LOG 08:17:22.405] [AddonLoader]: Instantiating addon 'HarmonyUserC' from assembly 'harmonytestC'
[LOG 08:17:22.406] HarmonyUser at D:\ksp\1.7.0\KSP_win64-1.7.0-harmonytest\GameData\TestC\harmonytestC.dll obtained Harmony 1.2.0.1 from D:\ksp\1.7.0\KSP_win64-1.7.0-harmonytest\GameData\0Harmony\0Harmony-C.dll
[LOG 08:17:22.410] [UIMasterController]: ShowUI
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment