예제 #1
0
 /// <summary>
 /// Returns the PluginMetadata of a provided BSIPA plugin
 /// </summary>
 public static PluginLoader.PluginMetadata GetPluginMetadata(IBeatSaberPlugin plugin)
 {
     foreach (PluginLoader.PluginInfo pluginInfo in PluginManager.AllPlugins)
     {
         if (pluginInfo != null && plugin == pluginInfo.GetPrivateProperty <IBeatSaberPlugin>("Plugin"))
         {
             return(pluginInfo.Metadata ?? null);
         }
     }
     return(null);
 }
예제 #2
0
 /// <summary>
 /// Called after a plugin has been fully initialized, whether or not there is an `Init` method. This should never throw an exception.
 /// </summary>
 /// <param name="plugin">the plugin that was just initialized</param>
 /// <param name="pluginInstance">the instance of the plugin being initialized</param>
 public virtual void AfterInit(PluginLoader.PluginInfo plugin, IBeatSaberPlugin pluginInstance) => AfterInit(plugin);
예제 #3
0
 /// <summary>
 /// Gets the ModPrefs object for the provided plugin.
 /// </summary>
 /// <param name="plugin">the plugin wanting the prefrences</param>
 /// <returns>the ModPrefs object</returns>
 public static IModPrefs GetModPrefs(this IBeatSaberPlugin plugin)
 {
     return(ModPrefs.ModPrefses.First(o => o.Key == plugin).Value);
 }
예제 #4
0
 /// <summary>
 /// Constructs a ModPrefs object for the provide plugin.
 /// </summary>
 /// <param name="plugin">the plugin to get the preferences file for</param>
 public ModPrefs(IBeatSaberPlugin plugin)
 {
     Instance = new IniFile(Path.Combine(Environment.CurrentDirectory, "UserData", "ModPrefs", $"{plugin.Name}.ini"));
     ModPrefses.Add(plugin, this);
 }
        private static Tuple <IEnumerable <BSPluginMeta>, IEnumerable <IPlugin> > LoadPluginsFromFile(string file, string exeName)
        {
            List <BSPluginMeta> bsPlugins  = new List <BSPluginMeta>();
            List <IPlugin>      ipaPlugins = new List <IPlugin>();

            if (!File.Exists(file) || !file.EndsWith(".dll", true, null))
            {
                return(new Tuple <IEnumerable <BSPluginMeta>, IEnumerable <IPlugin> >(bsPlugins, ipaPlugins));
            }

            T OptionalGetPlugin <T>(Type t) where T : class
            {
                // use typeof() to allow for easier renaming (in an ideal world this compiles to a string, but ¯\_(ツ)_/¯)
                if (t.GetInterface(typeof(T).Name) != null)
                {
                    try
                    {
                        T        pluginInstance = Activator.CreateInstance(t) as T;
                        string[] filter         = null;

                        if (pluginInstance is IGenericEnhancedPlugin)
                        {
                            filter = ((IGenericEnhancedPlugin)pluginInstance).Filter;
                        }

                        if (filter == null || filter.Contains(exeName, StringComparer.OrdinalIgnoreCase))
                        {
                            return(pluginInstance);
                        }
                    }
                    catch (Exception e)
                    {
                        Logger.log.Error($"Could not load plugin {t.FullName} in {Path.GetFileName(file)}! {e}");
                    }
                }

                return(null);
            }

            try
            {
                Assembly assembly = Assembly.LoadFrom(file);

                foreach (Type t in assembly.GetTypes())
                {
                    IBeatSaberPlugin bsPlugin = OptionalGetPlugin <IBeatSaberPlugin>(t);
                    if (bsPlugin != null)
                    {
                        try
                        {
                            var init = t.GetMethod("Init", BindingFlags.Instance | BindingFlags.Public);
                            if (init != null)
                            {
                                var initArgs   = new List <object>();
                                var initParams = init.GetParameters();

                                LoggerBase modLogger = null;
                                IModPrefs  modPrefs  = null;

                                foreach (var param in initParams)
                                {
                                    var ptype = param.ParameterType;
                                    if (ptype.IsAssignableFrom(typeof(LoggerBase)))
                                    {
                                        if (modLogger == null)
                                        {
                                            modLogger = new StandardLogger(bsPlugin.Name);
                                        }
                                        initArgs.Add(modLogger);
                                    }
                                    else if (ptype.IsAssignableFrom(typeof(IModPrefs)))
                                    {
                                        if (modPrefs == null)
                                        {
                                            modPrefs = new ModPrefs(bsPlugin);
                                        }
                                        initArgs.Add(modPrefs);
                                    }
                                    else
                                    {
                                        initArgs.Add(ptype.GetDefault());
                                    }
                                }

                                init.Invoke(bsPlugin, initArgs.ToArray());
                            }

                            bsPlugins.Add(new BSPluginMeta
                            {
                                Plugin       = bsPlugin,
                                Filename     = file.Replace("\\.cache", ""), // quick and dirty fix
                                ModsaberInfo = bsPlugin.ModInfo
                            });
                        }
                        catch (AmbiguousMatchException)
                        {
                            Logger.log.Error($"Only one Init allowed per plugin");
                        }
                    }
                    else
                    {
                        IPlugin ipaPlugin = OptionalGetPlugin <IPlugin>(t);
                        if (ipaPlugin != null)
                        {
                            ipaPlugins.Add(ipaPlugin);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Logger.log.Error($"Could not load {Path.GetFileName(file)}! {e}");
            }

            return(new Tuple <IEnumerable <BSPluginMeta>, IEnumerable <IPlugin> >(bsPlugins, ipaPlugins));
        }
        private static bool LoadAssembly(Type[] types, string filename)
        {
            var asm = types.First().Assembly;

            Logger.log.SuperVerbose($"Checking for plugins in {asm.GetName().Name}");

            List <Tuple <Type, BeatSaberPluginAttribute> > modTypes = new List <Tuple <Type, BeatSaberPluginAttribute> >();

            foreach (var type in types)
            {
                Logger.log.SuperVerbose($"Checking {type.FullName}");
                if (type.IsDefined(typeof(BeatSaberPluginAttribute), false))
                { // marked a plugin, but is it actually?
                    Logger.log.SuperVerbose($"Found attribute on {type.FullName}");
                    if (type.GetInterfaces().Contains(typeof(IBeatSaberPlugin)))
                    { // also actually a plugin! great!
                        Logger.log.SuperVerbose($"Found plugin {type.FullName}");
                        modTypes.Add(new Tuple <Type, BeatSaberPluginAttribute>(type, type.GetCustomAttribute <BeatSaberPluginAttribute>()));
                    }
                }
            }

            if (modTypes.Count == 0)
            {
                //Logger.log.Warn($"Assembly {asm.GetName().Name} has the BeatSaberModule attribute, but defines no mods!");
                return(false);
            }

            string commonPrefix = modTypes.Select(t => t.Item1.FullName).FindCommonPrefix();

            int pluginsLoaded = 0;

            foreach (var type in modTypes)
            {
                string pluginFullName = $"{asm.GetName().Name}/{type.Item1.FullName.Replace(commonPrefix, "")}";

                string finalName = modTypes.Count == 1 ? asm.GetName().Name : pluginFullName;
                finalName = type.Item2.Name ?? finalName;

                try
                {
                    Logger.log.SuperVerbose($"Instantiating {finalName} ({type.Item1.FullName})");
                    IBeatSaberPlugin plugin = Activator.CreateInstance(type.Item1) as IBeatSaberPlugin;

                    LoggerBase logger = Logger.CreateLogger(finalName);
                    Logger.log.SuperVerbose($"Initializing {finalName}");
                    plugin.Init(logger);

                    plugins.Add(new PluginObject
                    {
                        FileName = filename,
                        Name     = finalName,
                        Plugin   = plugin,
                        Meta     = type.Item2
                    });
                    pluginsLoaded++;
                }
                catch (Exception e)
                {
                    Logger.log.Error($"Cannot initialize plugin {finalName}");
                    Logger.log.Debug(e);
                }
            }

            Logger.log.SuperVerbose($"Plugins loaded from {asm.GetName().Name}: {pluginsLoaded}");

            if (pluginsLoaded == 0)
            {
                Logger.log.Error($"No plugins could be loaded from {asm.GetName().Name}.");
                return(false);
            }
            return(true);
        }