public void Start()
{
// Checkers are identified by the type name and version field name.
FieldInfo[] fields =
getAllTypes()
.Where(t => t.Name == "CompatibilityChecker")
.Select(t => t.GetField("_version", BindingFlags.Static | BindingFlags.NonPublic))
.Where(f => f != null)
.Where(f => f.FieldType == typeof(int))
.ToArray();
// Let the latest version of the checker execute.
if (_version != fields.Max(f => (int)f.GetValue(null))) { return; }
Debug.Log(String.Format("[CompatibilityChecker] Running checker version {0} from '{1}'", _version, Assembly.GetExecutingAssembly().GetName().Name));
// Other checkers will see this version and not run.
// This accomplishes the same as an explicit "ran" flag with fewer moving parts.
_version = int.MaxValue;
// A mod is incompatible if its compatibility checker has an IsCompatible method which returns false.
String[] incompatible =
fields
.Select(f => f.DeclaringType.GetMethod("IsCompatible", Type.EmptyTypes))
.Where(m => m.IsStatic)
.Where(m => m.ReturnType == typeof(bool))
.Where(m =>
{
try
{
return !(bool)m.Invoke(null, new object[0]);
}
catch (Exception e)
{
// If a mod throws an exception from IsCompatible, it's not compatible.
Debug.LogWarning(String.Format("[CompatibilityChecker] Exception while invoking IsCompatible() from '{0}':\n\n{1}", m.DeclaringType.Assembly.GetName().Name, e));
return true;
}
})
.Select(m => m.DeclaringType.Assembly.GetName().Name)
.ToArray();
Array.Sort(incompatible);
if (incompatible.Length > 0)
{
Debug.LogWarning("[CompatibilityChecker] Incompatible mods detected: " + String.Join(", ", incompatible));
PopupDialog.SpawnPopupDialog("Incompatible Mods Detected", "Some installed mods are incompatible with this version of Kerbal Space Program. Some features may be broken or disabled. Please check for updates to the following mods:\n\n" + String.Join("\n", incompatible), "OK", false, HighLogic.Skin);
}
}