Skip to content

Commit 7bd1e20

Browse files
committed
Complete revamp of the configuration system and M.O., allowing better modularization and partial deployment.
1 parent 8206145 commit 7bd1e20

File tree

7 files changed

+237
-137
lines changed

7 files changed

+237
-137
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
WatchDog
2+
{
3+
Interstellar_Redist
4+
{
5+
knownClient = Interstellar
6+
knownClient = PhotonSail
7+
}
8+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
WatchDog
2+
{
3+
Scale_Redist
4+
{
5+
knownClient = FerramAerospaceResearch
6+
knownClient = InfernalRobotics
7+
knownClient = InfernalRobotics_v3
8+
knownClient = Interstellar
9+
knownClient = InterstellarFuelSwitch
10+
knownClient = ODFC
11+
knownClient = PhotonSail
12+
knownClient = RoboBrakes
13+
knownClient = Scale
14+
knownClient = Scale_TweakableEverything
15+
knownClient = TweakScalerKISInventory
16+
knownClient = TweakScalerFSBuoyancy
17+
knownClient = TweakScalerWaterfallFX
18+
knownClient = TweakScale_RealFuels
19+
knownClient = modularFuelTanks
20+
}
21+
}
Lines changed: 17 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,21 @@
11
WatchDog
22
{
3-
EnforceRulesFromKSPVersion = 1.8
3+
// Force the current KSP version to be enforced as it would be this one.
4+
// Besides not being strictly needed on KSP <= 1.7, enforcing the rules
5+
// below will make KSP run faster, as duplicated Assemblies on memory
6+
// are a known source of performance issues and having them on non
7+
// standard places makes thing harder to diagnose when something goes
8+
// down through the tubes.
9+
//
10+
// Comment the following line if you prefer to have multiple
11+
// Assemblies around on older KSPs. **Patching with MM does not works**
12+
// as this tool runs before MM can process the patches (but may or may
13+
// not work when MM loads the cache - in doubt, don't patch).
14+
ForceRulesAsItWas = 1.12
415
5-
Scale_Redist
6-
{
7-
knownClient = FerramAerospaceResearch
8-
knownClient = InfernalRobotics
9-
knownClient = InfernalRobotics_v3
10-
knownClient = Interstellar
11-
knownClient = InterstellarFuelSwitch
12-
knownClient = ODFC
13-
knownClient = PhotonSail
14-
knownClient = RoboBrakes
15-
knownClient = Scale
16-
knownClient = Scale_TweakableEverything
17-
knownClient = TweakScalerKISInventory
18-
knownClient = TweakScalerFSBuoyancy
19-
knownClient = TweakScalerWaterfallFX
20-
knownClient = TweakScale_RealFuels
21-
knownClient = modularFuelTanks
22-
}
23-
24-
Interstellar_Redist
25-
{
26-
knownClient = Interstellar
27-
knownClient = PhotonSail
28-
}
16+
EnforceRulesFor = 1.8
17+
EnforceRulesFor = 1.9
18+
EnforceRulesFor = 1.10
19+
EnforceRulesFor = 1.11
20+
EnforceRulesFor = 1.12
2921
}

Source/ModuleManagerWatchDog/Startup.cs

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ You should have received a copy of the SKL Standard License 1.0
1818
using System;
1919
using System.Collections.Generic;
2020
using System.Linq;
21-
21+
using System.Reflection;
2222
using UnityEngine;
2323

2424
namespace ModuleManagerWatchDog
@@ -32,25 +32,17 @@ private void Start()
3232

3333
try
3434
{
35-
{
36-
String msg = CheckMyself();
37-
if ( null != msg )
38-
GUI.ShowStopperAlertBox.Show(msg);
39-
}
40-
41-
// On KSP < 1.8, duplicated Module Managers are not a problem, besides being a good idea to avoid them.
42-
// By not being a problem, I let the user choose or not to be pickly (I am!) by patching the respective value on the
43-
// configuration Config.
44-
if (SanityLib.IsExempted(Versioning.version_major, Versioning.version_minor))
45-
return;
46-
47-
{
48-
String msg = CheckModuleManager();
49-
if ( null != msg )
50-
GUI.ShowStopperAlertBox.Show(msg);
51-
else
52-
Log.info("Module Manager is good to go.");
53-
}
35+
// Always check for being the unique Assembly loaded. This will avoid problems in the future.
36+
String msg = CheckMyself();
37+
38+
if (null == msg)
39+
msg = CheckModuleManager();
40+
41+
if (null == msg && SanityLib.IsEnforceable(1, 8))
42+
msg = CheckModuleManager18();
43+
44+
if ( null != msg )
45+
GUI.ShowStopperAlertBox.Show(msg);
5446
}
5547
catch (Exception e)
5648
{
@@ -59,26 +51,35 @@ private void Start()
5951
}
6052
}
6153

62-
private String CheckMyself()
54+
private const string ASSEMBLY_NAME = "ModuleManager";
55+
56+
private string CheckMyself()
6357
{
64-
IEnumerable<AssemblyLoader.LoadedAssembly> loaded = SanityLib.FetchDllsByAssemblyName("ModuleManagerWatchDog");
58+
IEnumerable<AssemblyLoader.LoadedAssembly> loaded = SanityLib.FetchLoadedAssembliesByName(this.GetType().Namespace);
6559

6660
// Obviously, would be pointless to check for it not being installed! (0 == count). :)
6761
if (1 != loaded.Count()) return "There're more than one MM Watch Dog on this KSP installment! Please delete all but the one you intend to use!";
68-
if (!SanityLib.CheckIsOnGameData(loaded.First<AssemblyLoader.LoadedAssembly>().path))
62+
if (!SanityLib.CheckIsOnGameData(loaded.First().path))
6963
return "666_ModuleManagerWatchDog.dll <b>must be</b> directly on GameData and not inside any subfolder (i.e., it must be in the same place ModuleManager.dll is). Please move 666_ModuleManagerWatchDog.dll directly into GameData.";
7064
return null;
7165
}
7266

73-
private String CheckModuleManager()
67+
private string CheckModuleManager()
7468
{
75-
IEnumerable<AssemblyLoader.LoadedAssembly> loaded = SanityLib.FetchDllsByAssemblyName("ModuleManager");
69+
IEnumerable<AssemblyLoader.LoadedAssembly> loaded = SanityLib.FetchLoadedAssembliesByName(ASSEMBLY_NAME);
7670

7771
if (0 == loaded.Count()) return "There's no Module Manager on this KSP installment! You need to install Module Manager!";
78-
if (1 != loaded.Count()) return "There're more than one Module Manager on this KSP installment! Please delete all but the one you intend to use!";
79-
if (!SanityLib.CheckIsOnGameData(loaded.First<AssemblyLoader.LoadedAssembly>().path))
72+
if (!SanityLib.CheckIsOnGameData(loaded.First().path))
8073
return "ModuleManager.dll <b>must be</b> directly on GameData and not inside any subfolder. Please move ModuleManager.dll directly into GameData.";
8174
return null;
8275
}
76+
77+
private string CheckModuleManager18()
78+
{
79+
IEnumerable<System.Reflection.Assembly> loaded = SanityLib.FetchAssembliesByName(ASSEMBLY_NAME);
80+
81+
if (1 != loaded.Count()) return "There're more than one Module Manager on this KSP installment! Please delete all but the one you intend to use!";
82+
return null;
83+
}
8384
}
8485
}

Source/ModuleManagerWatchDog/Util/SanityLib.cs

Lines changed: 60 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -25,61 +25,97 @@ namespace ModuleManagerWatchDog
2525
{
2626
public static class SanityLib
2727
{
28-
private static string _EnforcedVersion;
29-
public static bool IsExempted(int kspMajor, int kspMinor)
28+
public static bool IsEnforceable(int kspMajor, int kspMinor)
3029
{
3130
ConfigNode cn = GameDatabase.Instance.GetConfigNode("ModuleManagerWatchDog/WatchDog");
32-
if (null != cn)
33-
{
34-
string value = cn.GetValue("EnforceRulesFromKSPVersion");
35-
_EnforcedVersion = string.IsNullOrEmpty(value) ? "1.8" : value;
31+
if (null == cn) return false;
32+
33+
int versionMajor = Versioning.version_major;
34+
int versionMinor = Versioning.version_minor;;
35+
{
36+
string versionOverride = cn.GetValue("ForceRulesAsItWas");
37+
if (null != versionOverride) try
38+
{
39+
string[] v = versionOverride.Split('.');
40+
versionMajor = Int16.Parse(v[0]);
41+
versionMinor = Int16.Parse(v[1]);
42+
}
43+
catch
44+
{
45+
versionMajor = Versioning.version_major;
46+
versionMinor = Versioning.version_minor;
47+
}
3648
}
3749

38-
try
50+
bool r = false;
51+
string[] enforcedRules = cn.GetValues("EnforceRulesFor");
52+
foreach (string ev in enforcedRules) try
3953
{
40-
string[] v = _EnforcedVersion.Split('.');
41-
bool r =
42-
kspMajor <= Int16.Parse(v[0])
54+
string[] v = ev.Split('.');
55+
r =
56+
versionMajor >= kspMajor
57+
&&
58+
versionMinor >= kspMinor
4359
&&
44-
kspMinor < Int16.Parse(v[1])
60+
kspMajor == Int16.Parse(v[0])
61+
&&
62+
kspMinor == Int16.Parse(v[1])
4563
;
46-
Log.dbg("Current version {0}.{1} is{2}exempted, as the rules enforced are from KSP {3}."
47-
, kspMajor, kspMinor
48-
, r ? " " : " not "
49-
, _EnforcedVersion
50-
);
51-
return r;
64+
if (r) break;
5265
}
5366
catch (Exception e)
5467
{
55-
Log.error("CheckIsEnvorceable : {0}. Rules are being enforced.", e.ToString());
68+
Log.error("IsEnforceable : {0}. Rules are being enforced.", e.ToString());
5669
return true;
5770
}
71+
72+
Log.detail("Current version {0}.{1} is{2}enforced on rules for {3}.{4}."
73+
, Versioning.version_major, Versioning.version_minor
74+
, r ? " " : " not "
75+
, kspMajor, kspMinor
76+
);
77+
return r;
5878
}
5979

60-
public static IEnumerable<AssemblyLoader.LoadedAssembly> FetchDllsByAssemblyName(string assemblyName)
80+
/**
81+
* If you need to fetch Assemblies being loaded or not (i.e., including the ones that KSP
82+
* didn't managed to finish the loading by faulty dependencies), you need to use this one.
83+
*/
84+
public static IEnumerable<System.Reflection.Assembly> FetchAssembliesByName(string assemblyName)
6185
{
86+
return from a in System.AppDomain.CurrentDomain.GetAssemblies()
87+
where assemblyName == a.GetName().Name
88+
orderby a.Location ascending
89+
select a
90+
;
91+
}
92+
93+
/**
94+
* If you are interested only on assemblies that were properly loaded by KSP, this is the one you want.
95+
*/
96+
public static IEnumerable<AssemblyLoader.LoadedAssembly> FetchLoadedAssembliesByName(string assemblyName)
97+
{
6298
return from a in AssemblyLoader.loadedAssemblies
6399
let ass = a.assembly
64100
where assemblyName == ass.GetName().Name
65101
orderby a.path ascending
66-
select a;
102+
select a
103+
;
67104
}
68105

69106
public static bool CheckIsOnGameData(string path, string filename = null)
70107
{
71108
string fullpath = Path.GetFullPath(path);
72109
string[] subpaths = Path.GetDirectoryName(fullpath).Split(Path.DirectorySeparatorChar);
73-
return "GameData" == subpaths[subpaths.Length-1] && (null == filename) ? true : filename == Path.GetFileName(fullpath);
110+
return "GameData" == subpaths[subpaths.Length-1] && ((null == filename) || filename == Path.GetFileName(fullpath));
74111
}
75112

76113
public static string[] GetFromConfig(string nodeName, string valueName)
77114
{
78-
ConfigNode cn = GameDatabase.Instance.GetConfigNode("ModuleManagerWatchDog/WatchDog");
115+
nodeName = nodeName.Replace("_", "");
116+
ConfigNode cn = GameDatabase.Instance.GetConfigNode("ModuleManagerWatchDog/Plugins/"+nodeName+"/"+nodeName);
79117
if (null == cn) return new string[]{};
80118
if ("WatchDog" != cn.name) return new string[]{};
81-
cn = cn.GetNode(nodeName);
82-
if (null == cn) return new string[]{};
83119
return cn.GetValues(valueName);
84120
}
85121
}

Source/WatchDogForInterstellarRedist/Startup.cs

Lines changed: 52 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -35,23 +35,27 @@ private void Start()
3535
try
3636
{
3737
// Always check for being the unique Assembly loaded. This will avoid problems in the future.
38-
{
39-
String msg = CheckMyself();
40-
if ( null != msg )
41-
GUI.ShowStopperAlertBox.Show(msg);
42-
}
38+
String msg = CheckMyself();
39+
40+
// If no known clients found, no need to further checks.
41+
if (null == msg && IsNeeded())
42+
{
43+
Log.detail("Clients found. Checking integrity...");
4344

44-
// On KSP < 1.8, duplicated Redists are not a problem, besides being a good idea to avoid them.
45-
// By not being a problem, I let the user choose or not to be pickly (I am!) by patching the respective value on the
46-
// configuration Config.
47-
if (SanityLib.IsExempted(Versioning.version_major, Versioning.version_minor))
48-
return;
45+
if ( null == msg )
46+
msg = CheckRedist();
4947

50-
{
51-
String msg = CheckRedist();
52-
if ( null != msg )
53-
GUI.ShowStopperAlertBox.Show(msg);
48+
if (null == msg && SanityLib.IsEnforceable(1, 8))
49+
msg = CheckRedist18();
50+
51+
if (null == msg)
52+
Log.detail("System is good to go.");
5453
}
54+
else
55+
Log.detail("No clients found. Sanity Check aborted.");
56+
57+
if ( null != msg )
58+
GUI.ShowStopperAlertBox.Show(msg);
5559
}
5660
catch (Exception e)
5761
{
@@ -60,33 +64,50 @@ private void Start()
6064
}
6165
}
6266

63-
private String CheckMyself()
67+
private const string ASSEMBLY_NAME = "Interstellar_Redist";
68+
private const string DLL_FILENAME = "Interstellar_Redist.dll";
69+
private const string ERR_MULTIPLE_TOOL = "There're more than one Interstellar Redist Watch Dog on this KSP installment! Please delete all but the one on GameData/ModuleManagerWatchDog/Plugins !";
70+
private const string ERR_MISSING_DLL = "There's no Interstellar Redist dll on this KSP installment, besides you having installed known DLL(s) that need it!!";
71+
private const string ERR_MULTIPLE_DLL = "There're more than one Interstellar Redist dll on this KSP installment! Please delete all but the GameData/Interstellar_Redist.dll one!";
72+
private const string ERR_MISPLACED_DLL = "Interstellar Redist dll <b>must be</b> directly on GameData and not inside any subfolder. Please move Interstellar_Redist.dll directly into GameData.";
73+
74+
private string CheckMyself()
6475
{
65-
IEnumerable<AssemblyLoader.LoadedAssembly> loaded = SanityLib.FetchDllsByAssemblyName("WatchDogForInterstellarRedist");
76+
IEnumerable<AssemblyLoader.LoadedAssembly> loaded = SanityLib.FetchLoadedAssembliesByName(this.GetType().Namespace);
6677

6778
// Obviously, would be pointless to check for it not being installed! (0 == count). :)
68-
if (1 != loaded.Count()) return "There're more than one Interstellar Redist Watch Dog on this KSP installment! Please delete all but the one on GameData/ModuleManagerWatchDog !";
79+
if (1 != loaded.Count()) return ERR_MULTIPLE_TOOL;
6980
return null;
7081
}
7182

72-
private String CheckRedist()
83+
private bool IsNeeded()
7384
{
74-
{
75-
string[] knownClients = SanityLib.GetFromConfig("Interstellar_Redist", "knownClient");
76-
bool found = false;
77-
foreach (string s in knownClients)
78-
found |= SanityLib.FetchDllsByAssemblyName(s).Any();
85+
string[] knownClients = SanityLib.GetFromConfig(ASSEMBLY_NAME, "knownClient");
7986

80-
// No known clients found, no need to check for it.
81-
if (!found) return null;
82-
}
87+
foreach (string s in knownClients) if (SanityLib.FetchAssembliesByName(s).Any())
88+
return true;
8389

84-
IEnumerable<AssemblyLoader.LoadedAssembly> loaded = SanityLib.FetchDllsByAssemblyName("Interstellar_Redist");
90+
return false;
91+
}
92+
93+
private string CheckRedist()
94+
{
95+
IEnumerable<AssemblyLoader.LoadedAssembly> loaded = SanityLib.FetchLoadedAssembliesByName(ASSEMBLY_NAME);
96+
Log.detail("{0}", loaded.Count());
97+
if (0 == loaded.Count()) return ERR_MISSING_DLL;
98+
return null;
99+
}
100+
101+
// On KSP < 1.8, duplicated Redists are not a problem, besides being a good idea to avoid them.
102+
// However, KSP 1.12 mangled a bit how DLLs are loaded, masking when more than one Assembly with the same name is loaded.
103+
// This may render the diagnosis a bit confusing
104+
private string CheckRedist18()
105+
{
106+
IEnumerable<AssemblyLoader.LoadedAssembly> loaded = SanityLib.FetchLoadedAssembliesByName(ASSEMBLY_NAME);
85107

86-
if (0 == loaded.Count()) return "There's no Interstellar Redist dll on this KSP installment, besides you having installed known DLL(s) that need it!!";
87-
if (1 != loaded.Count()) return "There're more than one Interstellar Redist dll on this KSP installment! Please delete all but the GameData/Interstellar_Redist.dll one!";
88-
if (!SanityLib.CheckIsOnGameData(loaded.First<AssemblyLoader.LoadedAssembly>().path, "Interstellar_Redist.dll"))
89-
return "Interstellar Redist dll <b>must be</b> directly on GameData and not inside any subfolder. Please move Interstellar_Redist.dll directly into GameData.";
108+
if (1 != loaded.Count()) return ERR_MULTIPLE_DLL;
109+
if (!SanityLib.CheckIsOnGameData(loaded.First().path, DLL_FILENAME))
110+
return ERR_MISPLACED_DLL;
90111
return null;
91112
}
92113
}

0 commit comments

Comments
 (0)