View difference between Paste ID: xpexbAZd and FtUSL0pu
SHOW: | | - or go back to the newest paste.
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 (SixtyFourBitsMayHaveAChanceAtLife())
153+
154-
             *{
154+
155-
             *   message += "WARNING: You are using 64-bit KSP on Windows. This version of KSP is known to cause crashes. It's highly recommended that you use either 32-bit KSP on Windows or switch to Linux.";
155+
156-
             *}*/
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-
        public static bool IsAllCompatible()
183+
184
                {
185-
            return IsCompatible() && IsUnityCompatible();
185+
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
}