Advertisement
Guest User

CompatibilityChecker 6 - updated

a guest
May 31st, 2017
53
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /* Copyright (c) 2016, Majiir, ferram4
  2.  * All rights reserved.
  3.  *
  4.  * Redistribution and use in source and binary forms, with or without modification, are permitted
  5.  * provided that the following conditions are met:
  6.  *
  7.  * 1. Redistributions of source code must retain the above copyright notice, this list of
  8.  * conditions and the following disclaimer.
  9.  *
  10.  * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
  11.  * conditions and the following disclaimer in the documentation and/or other materials provided
  12.  * with the distribution.
  13.  *
  14.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
  15.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  16.  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
  17.  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  18.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  19.  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  20.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  21.  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  22.  * POSSIBILITY OF SUCH DAMAGE. */
  23.  
  24. using System;
  25. using System.Collections.Generic;
  26. using System.Linq;
  27. using System.Reflection;
  28. using UnityEngine;
  29.  
  30. /*-----------------------------------------*\
  31. |   SUBSTITUTE YOUR MOD'S NAMESPACE HERE.   |
  32. \*-----------------------------------------*/
  33. namespace RealChute
  34. {
  35.     /* This utility displays a warning with a list of mods that determine themselves
  36.      * to be incompatible with the current running version of Kerbal Space Program.
  37.      *
  38.      * See this forum thread for details:
  39.      * http://forum.kerbalspaceprogram.com/threads/65395-Voluntarily-Locking-Plugins-to-a-Particular-KSP-Version */
  40.     [KSPAddon(KSPAddon.Startup.Instantly, true)]
  41.     internal class CompatibilityChecker : MonoBehaviour
  42.     {
  43.         public static bool IsCompatible()
  44.         {
  45.             /*-----------------------------------------------*\
  46.             |    BEGIN IMPLEMENTATION-SPECIFIC EDITS HERE.    |
  47.             \*-----------------------------------------------*/
  48.            
  49.             //
  50.             //If you want to disable some behavior when incompatible, other parts of the plugin
  51.             //should query this method:
  52.             //
  53.             //    if (!CompatibilityChecker.IsCompatible()) {
  54.             //        ...disable some features...
  55.             //    }
  56.             //
  57.             // Even if you don't lock down functionality, you should return true if your users
  58.             // can expect a future update to be available.
  59.             //
  60.             return true;
  61.  
  62.             /*-----------------------------------------------*\
  63.             | IMPLEMENTERS SHOULD NOT EDIT BEYOND THIS POINT! |
  64.             \*-----------------------------------------------*/
  65.         }
  66.  
  67.         public static bool IsUnityCompatible()
  68.         {
  69.             /*-----------------------------------------------*\
  70.             |    BEGIN IMPLEMENTATION-SPECIFIC EDITS HERE.    |
  71.             \*-----------------------------------------------*/
  72.            
  73.             return true;
  74.  
  75.             /*-----------------------------------------------*\
  76.             | IMPLEMENTERS SHOULD NOT EDIT BEYOND THIS POINT! |
  77.             \*-----------------------------------------------*/
  78.         }
  79.  
  80.         //Version of the compatibility checker itself.
  81.         private static int _version = 6;
  82.  
  83.         public void Start()
  84.         {
  85.             //Checkers are identified by the type name and _version field name.
  86.             FieldInfo[] fields =
  87.                 GetAllTypes()
  88.                 .Where(t => t.Name == "CompatibilityChecker")
  89.                 .Select(t => t.GetField("_version", BindingFlags.Static | BindingFlags.NonPublic))
  90.                 .Where(f => f != null)
  91.                 .Where(f => f.FieldType == typeof(int))
  92.                 .ToArray();
  93.  
  94.             //Let the latest version of the checker execute.
  95.             if (_version != fields.Max(f => (int)f.GetValue(null))) { return; }
  96.  
  97.             Debug.Log(string.Format("[CompatibilityChecker] Running checker version {0} from '{1}'", _version, Assembly.GetExecutingAssembly().GetName().Name));
  98.  
  99.             //Other checkers will see this version and not run.
  100.             //This accomplishes the same as an explicit "ran" flag with fewer moving parts.
  101.             _version = int.MaxValue;
  102.  
  103.             //A mod is incompatible if its compatibility checker has an IsCompatible method which returns false.
  104.             string[] incompatible =
  105.                 fields
  106.                 .Select(f => f.DeclaringType.GetMethod("IsCompatible", Type.EmptyTypes))
  107.                 .Where(m => m.IsStatic)
  108.                 .Where(m => m.ReturnType == typeof(bool))
  109.                 .Where(m =>
  110.                 {
  111.                     try
  112.                     {
  113.                         return !(bool)m.Invoke(null, new object[0]);
  114.                     }
  115.                     catch (Exception e)
  116.                     {
  117.                         //If a mod throws an exception from IsCompatible, it's not compatible.
  118.                         Debug.LogWarning(string.Format("[CompatibilityChecker] Exception while invoking IsCompatible() from '{0}':\n\n{1}", m.DeclaringType.Assembly.GetName().Name, e));
  119.                         return true;
  120.                     }
  121.                 })
  122.                 .Select(m => m.DeclaringType.Assembly.GetName().Name)
  123.                 .ToArray();
  124.  
  125.             //A mod is incompatible with Unity if its compatibility checker has an IsUnityCompatible method which returns false.
  126.             string[] incompatibleUnity =
  127.                 fields
  128.                 .Select(f => f.DeclaringType.GetMethod("IsUnityCompatible", Type.EmptyTypes))
  129.                 .Where(m => m != null)  //Mods without IsUnityCompatible() are assumed to be compatible.
  130.                 .Where(m => m.IsStatic)
  131.                 .Where(m => m.ReturnType == typeof(bool))
  132.                 .Where(m =>
  133.                 {
  134.                     try
  135.                     {
  136.                         return !(bool)m.Invoke(null, new object[0]);
  137.                     }
  138.                     catch (Exception e)
  139.                     {
  140.                         //If a mod throws an exception from IsUnityCompatible, it's not compatible.
  141.                         Debug.LogWarning(string.Format("[CompatibilityChecker] Exception while invoking IsUnityCompatible() from '{0}':\n\n{1}", m.DeclaringType.Assembly.GetName().Name, e));
  142.                         return true;
  143.                     }
  144.                 })
  145.                 .Select(m => m.DeclaringType.Assembly.GetName().Name)
  146.                 .ToArray();
  147.  
  148.             Array.Sort(incompatible);
  149.             Array.Sort(incompatibleUnity);
  150.  
  151.             string message = string.Empty;
  152.  
  153.             if (incompatible.Length > 0 || incompatibleUnity.Length > 0)
  154.             {
  155.                 message += (message == string.Empty ? "Some" : "\n\nAdditionally, some") + " installed mods may be incompatible with this version of Kerbal Space Program. Features may be broken or disabled. Please check for updates to the listed mods.";
  156.  
  157.                 if (incompatible.Length > 0)
  158.                 {
  159.                     Debug.LogWarning("[CompatibilityChecker] Incompatible mods detected: " + string.Join(", ", incompatible));
  160.                     message += string.Format("\n\nThese mods are incompatible with KSP {0}.{1}.{2}:\n\n", Versioning.version_major, Versioning.version_minor, Versioning.Revision);
  161.                     message += string.Join("\n", incompatible);
  162.                 }
  163.  
  164.                 if (incompatibleUnity.Length > 0)
  165.                 {
  166.                     Debug.LogWarning("[CompatibilityChecker] Incompatible mods (Unity) detected: " + string.Join(", ", incompatibleUnity));
  167.                     message += string.Format("\n\nThese mods are incompatible with Unity {0}:\n\n", Application.unityVersion);
  168.                     message += string.Join("\n", incompatibleUnity);
  169.                 }
  170.             }
  171.  
  172.             if (incompatible.Length > 0 || incompatibleUnity.Length > 0)
  173.             {
  174.                 PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), "CompatibilityChecker", "Incompatible Mods Detected", message, "OK", true, HighLogic.UISkin);
  175.             }
  176.         }
  177.  
  178.         private static IEnumerable<Type> GetAllTypes()
  179.         {
  180.             foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
  181.             {
  182.                 Type[] types;
  183.                 try
  184.                 {
  185.                     types = assembly.GetTypes();
  186.                 }
  187.                 catch (Exception)
  188.                 {
  189.                     types = Type.EmptyTypes;
  190.                 }
  191.  
  192.                 foreach (Type type in types)
  193.                 {
  194.                     yield return type;
  195.                 }
  196.             }
  197.         }
  198.     }
  199. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement