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 | } |