Exemple #1
0
        /// <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.");
        }