/// <summary> /// Loads the game information. /// </summary> private static void LoadGameInfo() { Main.Log.AppendLine("Loading game library."); List <FileInfo> found = new List <FileInfo>(); DirectoryInfo dir = new DirectoryInfo("Data\\NetScriptFramework"); var files = dir.GetFiles(); foreach (var x in files) { string fileName = x.Name; if (!fileName.EndsWith(".dll", StringComparison.OrdinalIgnoreCase) || !fileName.StartsWith(Main.FrameworkName + ".", StringComparison.OrdinalIgnoreCase) || fileName.Equals(Main.FrameworkName + ".dll", StringComparison.OrdinalIgnoreCase)) { continue; } fileName = fileName.Substring(Main.FrameworkName.Length + 1); fileName = fileName.Substring(0, fileName.Length - 4); if (fileName.Length == 0 || fileName.Equals("Runtime", StringComparison.OrdinalIgnoreCase)) { continue; } found.Add(x); } if (found.Count == 0) { Main.Log.AppendLine("No game library found! Game definitions will not be loaded but plugins may still load."); return; } if (found.Count > 1) { string fstr = string.Join(", ", found.Select(q => q.Name)); throw new InvalidOperationException("Found more than one game library DLL! Only one game library may be active at a time. [" + fstr + "]"); } { var debugFile = found[0]; string debugFileName = debugFile.Name; int ptIdx = debugFileName.LastIndexOf('.'); if (ptIdx >= 0) { debugFileName = debugFileName.Substring(0, ptIdx) + ".bin"; debugFile = new FileInfo(System.IO.Path.Combine(debugFile.DirectoryName, debugFileName)); CrashLog._FileForDebugInfo = debugFile; CrashLog.InitializeDebug(); } } System.Reflection.Assembly assembly = null; Loader.Load(found[0], ref assembly); if (assembly == null) { throw new InvalidOperationException(); } var types = assembly.GetTypes(); Type valid = null; foreach (var t in types) { if (!t.IsSubclassOf(typeof(Game))) { continue; } if (t.IsAbstract) { continue; } if (t.BaseType != typeof(Game)) { continue; } if (valid != null) { throw new InvalidOperationException("Found more than one valid game header type!"); } valid = t; } if (valid == null) { throw new InvalidOperationException("Found game library but no valid game header type!"); } GameCreate = 1; Main._is_initializing_plugin += 2; try { Game result = (Game)Activator.CreateInstance(valid); string print = "`" + result.FullName + "` (" + result.LibraryVersion + ")"; Main.Log.AppendLine("Loaded game library for " + print + "."); Main.Log.AppendLine("Running game version is " + string.Join(".", result.GameVersion)); string supportedExecutable = result.ExecutableName; string haveExecutable = System.Diagnostics.Process.GetCurrentProcess().MainModule.ModuleName; if (!haveExecutable.Equals(supportedExecutable, StringComparison.OrdinalIgnoreCase)) { throw new InvalidOperationException("Game library " + print + " expected game executable `" + supportedExecutable + "` but have `" + haveExecutable + "`!"); } if (!result.IsValidVersion) { throw new InvalidOperationException("Game library " + print + " does not support game version " + string.Join(".", result.GameVersion) + "!"); } Main.Game = result; result._initialize(); } finally { Main._is_initializing_plugin -= 2; } }
/// <summary> /// Processes the file for plugin loading. /// </summary> /// <param name="file">The file.</param> /// <param name="plugins">The plugins.</param> /// <returns></returns> /// <exception cref="System.InvalidOperationException"></exception> /// <exception cref="System.NotImplementedException"></exception> /// <exception cref="System.NullReferenceException"></exception> /// <exception cref="System.FormatException"></exception> private static void ProcessFile(FileInfo file, Dictionary <string, Plugin> plugins) { Main.Log.AppendLine("Checking file \"" + file.Name + "\"..."); Assembly assembly = null; Loader.Load(file, ref assembly); if (assembly == null) { throw new InvalidOperationException("Assembly failed to load and no exception was thrown!"); } var types = assembly.GetTypes(); int totalFound = 0; List <Type>[] found = new List <Type> [7]; List <ConstructorInfo> foundCis = new List <ConstructorInfo>(); for (int i = 0; i < found.Length; i++) { found[i] = new List <Type>(); } foreach (var t in types) { if (t == typeof(Plugin)) { totalFound++; found[1].Add(t); continue; } if (!t.IsSubclassOf(typeof(Plugin))) { var qt = t.BaseType; while (qt != null) { if (qt.Name == "Plugin") { totalFound++; found[2].Add(t); qt = null; break; } qt = qt.BaseType; } continue; } if (t.IsAbstract) { totalFound++; found[3].Add(t); continue; } if (t.BaseType != typeof(Plugin)) { totalFound++; found[6].Add(t); continue; } var constructors = t.GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); ConstructorInfo ci = null; foreach (var c in constructors) { if (ci == null) { ci = c; } else if (c.GetParameters().Length == 0) { ci = c; } } if (ci == null) { totalFound++; found[4].Add(t); continue; } if (ci.GetParameters().Length != 0) { totalFound++; found[5].Add(t); continue; } totalFound++; found[0].Add(t); foundCis.Add(ci); } if (totalFound == 0) { throw new InvalidOperationException("Failed to load (" + file.Name + ")! Plugin header info type was missing. If this is a dependency then place it in the libraries folder."); } if (found[0].Count > 1) { throw new InvalidOperationException("Found more than one valid plugin header type!"); } if (found[0].Count == 0) { if (found[5].Count != 0) { throw new InvalidOperationException("Found plugin header type but invalid constructor arguments!"); } if (found[4].Count != 0) { throw new InvalidOperationException("Found plugin header type but no constructor!"); } if (found[3].Count != 0) { throw new InvalidOperationException("Found plugin header type but it's marked abstract!"); } if (found[2].Count != 0) { throw new InvalidOperationException("Found plugin header type but inherited from an incompatible type! If this is a plugin module then try recompiling plugin."); } if (found[1].Count != 0) { throw new InvalidOperationException("Found plugin header type but it is not inherited from expected header type!"); } if (found[6].Count != 0) { throw new InvalidOperationException("Found plugin header type but it does not inherit directly from it!"); } throw new NotImplementedException(); } CreatingPlugin = 1; Plugin pluginInstance = (Plugin)(foundCis[0].Invoke(new object[0])); pluginInstance.Assembly = assembly; string key = pluginInstance.InternalKey; int _vr = pluginInstance.InternalVersion; // Init these, if it throws exception we should abort now. string _nm = pluginInstance.InternalName; pluginInstance.InternalIndex = ++HighPluginIndex; if (key == null) { throw new NullReferenceException("Plugin " + pluginInstance.GetInternalString() + " returned (null) as key!"); } if (key.Length == 0) { throw new FormatException("Plugin " + pluginInstance.GetInternalString() + " returned empty key!"); } int reqFramework = pluginInstance.RequiredFrameworkVersion; if (reqFramework > Main.FrameworkVersion) { throw new ArgumentException("Plugin " + pluginInstance.GetInternalString() + " requires a newer version of framework API! The .NET Framework must be updated before this plugin can be used."); } int reqLibrary = pluginInstance.RequiredLibraryVersion; int hasLibrary = Main.Game != null ? Main.Game.LibraryVersion : 0; if (reqLibrary > hasLibrary) { throw new ArgumentException("Plugin " + pluginInstance.GetInternalString() + " requires a newer version of game library (" + reqLibrary + ")! The .NET Framework must be updated before this plugin can be used."); } { Plugin d = null; if (plugins.TryGetValue(key, out d)) { string prev = d.GetInternalString(); string cur = pluginInstance.GetInternalString(); throw new InvalidOperationException("Plugin " + cur + " returned \"" + key + "\" as key! This is a duplicate of plugin " + prev + "! Multiple plugins with same key is not allowed."); } } plugins[key] = pluginInstance; Main.Log.AppendLine("Plugin found and loaded."); }