Provides info and functionality for calling reflected methods
        /// <summary>
        /// Registers a networkfunction so it can get called
        /// </summary>
        /// <param name="info">The functions info</param>
        public static void RegisterNetworkFunction(FunctionInfo info)
        {
            if (_networkFunctions.FirstOrDefault(f => f.Name.Equals(info.Name)) != null)
                return;

            _networkFunctions.Add(info);

            NetworkFunctionsChanged?.Invoke();
            //Debug.Log(_debugChannel, "Method '" + info.Name + "' has been added");
        }
        /// <summary>
        /// Loads all plugins in a directory
        /// </summary>
        /// <param name="dir">The DirectoryInfo for the destination directory</param>
        /// <param name="unloadablePlugins">Contains a List of plugins that could not be loaded</param>
        /// <returns>A List of loaded plugins</returns>
        private static void LoadFromDir(DirectoryInfo dir, out List<Type> unloadablePlugins)
        {
            if (dir == null || !dir.Exists) {
                unloadablePlugins = new List<Type>();
                return;
            }

            Debug.Log(_defaultDebugChannel, "Loading types...");
            List<Type> types = LoadTypes(dir);
            Debug.Log(_defaultDebugChannel, "Types found: " + types.Count);
            int loadedPlugins = -1;

            while (loadedPlugins != 0) {
                loadedPlugins = 0;

                List<Type> tempLoadedPlugins = new List<Type>();
                foreach (Type type in types) {
                    if (!NeededPluginsLoaded(type, _plugins))
                        continue;

                    Plugin plugin = type.InvokeMember(null, BindingFlags.CreateInstance, null, null, null) as Plugin;

                    Debug.Log(_defaultDebugChannel, "Plugin found: " + plugin.Name);

                    _plugins.Add(plugin);
                    plugin.OnPluginLoad();
                    loadedPlugins++;
                    tempLoadedPlugins.Add(type);
                    PluginLoad?.Invoke(plugin);

                    foreach(MethodInfo method in type.GetMethods()) {
                        foreach(Attribute attr in Attribute.GetCustomAttributes(method)) {
                            if(attr is NetworkFunction) {
                                NetworkFunction nfattr = (NetworkFunction)attr;

                                FunctionInfo info = new FunctionInfo(nfattr.Name, plugin, method);
                                NetworkManager.RegisterNetworkFunction(info);
                            }
                        }
                    }
                }

                foreach (Type type in tempLoadedPlugins)
                    types.Remove(type);
            }

            foreach (Plugin plugin in _plugins)
                plugin.OnPluginsLoad();

            Debug.Log(_defaultDebugChannel, "Unloadable Plugins: " + types.Count);

            unloadablePlugins = types;
        }