public void OnSelect(ModListController cntrl) { Logger.log.Debug($"Selected IPAModCell {Plugin.Name} {Plugin.Version}"); if (infoView == null) { PluginLoader.PluginMetadata updateInfo = null; try { updateInfo = new PluginLoader.PluginMetadata { Name = Plugin.Name, Id = Plugin.Name, Version = new SemVer.Version(Plugin.Version) }; } catch (Exception e) { Logger.log.Warn($"Could not generate fake update info for {Plugin.Name}"); Logger.log.Warn(e); } infoView = BeatSaberUI.CreateViewController <ModInfoViewController>(); infoView.Init(icon, Plugin.Name, "v" + Plugin.Version.ToString(), "<color=#BFBFBF><i>Unknown Author</i>", "This mod was written for IPA.\n===\n\n## No metadata is avaliable for this mod.\n\n" + "Please contact the mod author and ask them to port it to BSIPA to provide more information.", updateInfo); } list.flow.SetSelected(infoView, immediate: list.flow.HasSelected); }
public override bool Initialize(PluginLoader.PluginMetadata meta, string[] parameters) {// parameters should be (fully qualified name of provider type) if (parameters.Length != 1) { InvalidMessage = "Incorrect number of parameters"; return(false); } RequireLoaded(meta); Type getType; try { getType = meta.Assembly.GetType(parameters[0]); } catch (ArgumentException) { InvalidMessage = $"Invalid type name {parameters[0]}"; return(false); } catch (Exception e) when(e is FileNotFoundException || e is FileLoadException || e is BadImageFormatException) { string filename; switch (e) { case FileNotFoundException fn: filename = fn.FileName; goto hasFilename; case FileLoadException fl: filename = fl.FileName; goto hasFilename; case BadImageFormatException bi: filename = bi.FileName; hasFilename: InvalidMessage = $"Could not find {filename} while loading type"; break; default: InvalidMessage = $"Error while loading type: {e}"; break; } return(false); } try { Config.Config.Register(getType); return(true); } catch (Exception e) { InvalidMessage = $"Error generated while creating delegate: {e}"; return(false); } }
public void Init(Sprite icon, string name, string version, string author, string description, PluginLoader.PluginMetadata updateInfo, PluginManifest.LinksObject links = null) { Icon = icon; Name = name; Version = version; Author = author; Description = description; UpdateInfo = updateInfo; if (rowTransformOriginal == null) { rowTransformOriginal = MenuButtonUI.Instance.GetPrivateField <RectTransform>("menuButtonsOriginal"); } // i also have no clue why this is necessary rectTransform.anchorMin = new Vector2(0f, 0f); rectTransform.anchorMax = new Vector2(0.5f, 1f); var go = new GameObject("Info View", typeof(RectTransform)); go.SetActive(false); go.AddComponent <RectMask2D>(); view = go.AddComponent <ModInfoView>(); var rt = view.transform as RectTransform; rt.SetParent(transform); rt.anchorMin = new Vector2(0f, 0f); rt.anchorMax = new Vector2(1f, 1f); rt.anchoredPosition = new Vector2(0f, 0); view.Init(this); go.SetActive(true); SetupLinks(links); }
public override bool Initialize(PluginLoader.PluginMetadata meta, string[] parameters) { // parameters should be (name, fully qualified type) if (parameters.Length != 2) { InvalidMessage = "Incorrect number of parameters"; return(false); } RequireLoaded(meta); Type type; try { type = meta.Assembly.GetType(parameters[1]); } catch (ArgumentException) { InvalidMessage = $"Invalid type name {parameters[1]}"; return(false); } catch (Exception e) when(e is FileNotFoundException || e is FileLoadException || e is BadImageFormatException) { var filename = ""; switch (e) { case FileNotFoundException fn: filename = fn.FileName; break; case FileLoadException fl: filename = fl.FileName; break; case BadImageFormatException bi: filename = bi.FileName; break; } InvalidMessage = $"Could not find {filename} while loading type"; return(false); } try { if (RegisterFeature(parameters[0], type)) { return(NewFeature = true); } InvalidMessage = $"Feature with name {parameters[0]} already exists"; return(false); } catch (ArgumentException) { InvalidMessage = $"{type.FullName} not a subclass of {nameof(Feature)}"; return(false); } }
public override bool Initialize(PluginLoader.PluginMetadata meta, string[] parameters) { selfMeta = meta; RequireLoaded(meta); return(true); }
public void OnApplicationStart() { var harmony = HarmonyInstance.Create("com.Shoko84.beatsaber.FightSabers"); harmony.PatchAll(Assembly.GetExecutingAssembly()); fightSabersMetadata = PluginManager.AllPlugins.Select(x => x.Metadata).First(x => x.Name == "FightSabers"); BSEvents.menuSceneActive += OnMenuSceneActive; BSEvents.gameSceneActive += OnGameSceneActive; GameplaySetup.instance.AddTab("FS Modifiers", "FightSabers.UI.Views.FightSabersGameplaySetupView.bsml", FightSabersGameplaySetup.instance); }
public void Init(IPALogger log, PluginLoader.PluginMetadata metadata) { Logger = log; if (metadata != null) { PluginVersion = metadata.Version; Log("Version number set"); } }
public void Init(Sprite icon, string name, string version, string author, string description, PluginLoader.PluginMetadata updateInfo, PluginManifest.LinksObject links = null, bool showEnDis = false, ModListFlowCoordinator mlfc = null) { showEnableDisable = showEnDis; Plugin.OnConfigChaned -= OptHideButton; Icon = icon; Name = name; Version = version; Author = author; Description = description; UpdateInfo = updateInfo; enabled = !PluginManager.IsDisabled(updateInfo); flowController = mlfc; if (rowTransformOriginal == null) { rowTransformOriginal = MenuButtonUI.Instance.GetPrivateField <RectTransform>("menuButtonsOriginal"); } // i also have no clue why this is necessary rectTransform.anchorMin = new Vector2(0f, 0f); rectTransform.anchorMax = new Vector2(0.5f, 1f); var go = new GameObject("Info View", typeof(RectTransform)); go.SetActive(false); go.AddComponent <RectMask2D>(); view = go.AddComponent <ModInfoView>(); var rt = view.transform as RectTransform; rt.SetParent(transform); rt.anchorMin = new Vector2(0f, 0f); rt.anchorMax = new Vector2(1f, 1f); rt.anchoredPosition = new Vector2(0f, 0); view.Init(this); go.SetActive(true); if (showEnDis) { restartMessage = BeatSaberUI.CreateText(rectTransform, "A restart is required to apply", new Vector2(11f, 33.5f)); restartMessage.fontSize = 4f; restartMessage.gameObject.SetActive(false); enableDisableButton = BeatSaberUI.CreateUIButton(rectTransform, "CreditsButton", new Vector2(33, 32), new Vector2(25, 10), ToggleEnable); enableDisableButton.GetComponentInChildren <StartMiddleEndButtonBackgroundController>().SetMiddleSprite(); UpdateButtonText(); Plugin.OnConfigChaned += OptHideButton; OptHideButton(Plugin.config.Value); } SetupLinks(links); }
public static Sprite GetEmbeddedIcon(this PluginLoader.PluginMetadata meta) { if (embeddedIcons.TryGetValue(meta, out var sprite)) { return(sprite); } var icon = GetEmbeddedIconNoCache(meta); embeddedIcons.Add(meta, icon); return(icon); }
/// <summary> /// Adds an outside MonoBehaviour into the Counters+ system. /// <param name="model"/>The CustomCounter object.</param> /// <param name="defaults">Default configuration options for your custom counter.</param> /// <param name="restrictedPositions">Restrict your Custom Counter to any of these positions. Inputting no parameters would allow the Counter to use all that are available.</param> /// </summary> public static void Create <T>(T model, CustomConfigModel defaults = null, params ICounterPositions[] restrictedPositions) where T : CustomCounter { string modCreator = ""; if (model.Mod != null) { modCreator = model.Mod.Name; } if (model.BSIPAMod != null) { PluginLoader.PluginMetadata pluginMetadata = PluginUtility.GetPluginMetadata(model.BSIPAMod); if (pluginMetadata != null) { modCreator = pluginMetadata.Name; } } Plugin.Log($"Custom Counter ({model.Name}) added!", Plugin.LogInfo.Notice); foreach (CustomConfigModel potential in ConfigLoader.LoadCustomCounters()) { if (potential.DisplayName == model.Name) { if (potential.IsNew) { potential.IsNew = false; potential.Save(); } return; } } CustomConfigModel counter = new CustomConfigModel(model.Name) { DisplayName = model.Name, SectionName = model.SectionName, Enabled = (defaults == null ? true : defaults.Enabled), Position = (defaults == null ? ICounterPositions.BelowCombo : defaults.Position), Distance = (defaults == null ? 2 : defaults.Distance), Counter = model.Counter, ModCreator = modCreator, IsNew = true, RestrictedPositions = (restrictedPositions?.Count() == 0 || restrictedPositions == null) ? new ICounterPositions[] { } : restrictedPositions, //Thanks Viscoci for this }; if (string.IsNullOrEmpty(counter.SectionName) || string.IsNullOrEmpty(counter.DisplayName)) { throw new CustomCounterException("Custom Counter properties invalid. Please make sure SectionName and DisplayName are properly assigned."); } counter.Save(); }
public void Init(IPALogger logger, PluginLoader.PluginMetadata metadata) { if (logger != null) { Logger.logger = logger; Logger.Log("Logger prepared"); } if (metadata != null) { Plugin.PluginVersion = metadata.Version.ToString(); } }
public LibraryModCell(ModListController list, PluginLoader.PluginMetadata plugin) : base($"{plugin.Name} <size=60%>v{plugin.Version}", plugin.Manifest.Author, null) { Plugin = plugin; this.list = list; if (string.IsNullOrWhiteSpace(subtext)) { subtext = "<color=#BFBFBF><i>Unspecified Author</i></color>"; } icon = Utilities.DefaultLibraryIcon; }
public static Sprite GetIcon(this PluginLoader.PluginMetadata meta) { if (meta == null) { return(DefaultBSIPAIcon); } if (meta.IsBare) { return(DefaultLibraryIcon); } else { return(GetEmbeddedIcon(meta) ?? DefaultBSIPAIcon); } }
private static void PluginManager_PluginDisabled(PluginLoader.PluginMetadata plugin, bool needsRestart, WeakReference <BSIPAModCell> _self, PluginManager.PluginDisableDelegate ownDel) { if (!_self.TryGetTarget(out var self)) { PluginManager.PluginDisabled -= ownDel; return; } if (plugin != self.Plugin) { return; } self.Update(false, needsRestart); }
public BSIPAIgnoredModCell(ModListController list, PluginLoader.PluginMetadata plugin) : base($"<color=#878787>{plugin.Name} <size=60%>v{plugin.Version}", "", Utilities.DefaultBSIPAIcon) { Plugin = plugin; this.list = list; if (string.IsNullOrWhiteSpace(plugin.Manifest.Author)) { authorText = "<color=#BFBFBF><i>Unspecified Author</i>"; } else { authorText = plugin.Manifest.Author; } subtext = string.Format(authorFormat, authorText); }
public BSIPAModCell(ModListController list, PluginLoader.PluginMetadata plugin) : base("", "", null) { Plugin = plugin; this.list = list; var thisWeakRef = new WeakReference <BSIPAModCell>(this); PluginManager.PluginDisableDelegate reflessDDel = null; reflessDDel = disableDel = (p, r) => PluginManager_PluginDisabled(p, r, thisWeakRef, reflessDDel); // some indirection to make it a weak link for GC PluginManager.PluginDisabled += reflessDDel; PluginManager.PluginEnableDelegate reflessEDel = null; reflessEDel = enableDel = (p, r) => PluginManager_PluginEnabled(p, r, thisWeakRef, reflessEDel); // some indirection to make it a weak link for GC PluginManager.PluginEnabled += reflessEDel; Update(propogate: false); }
/// <summary> /// Returns the PluginMetadata of a loaded BSIPA plugin /// </summary> public static PluginLoader.PluginMetadata GetPluginMetadata(string pluginName) { if (IsPluginPresent(pluginName)) { PluginLoader.PluginMetadata metadataFromName = PluginManager.GetPlugin(pluginName).Metadata; PluginLoader.PluginMetadata metadataFromId = PluginManager.GetPluginFromId(pluginName).Metadata; if (metadataFromName != null) { return(metadataFromName); } else if (metadataFromId != null) { return(metadataFromId); } } return(null); }
private static Sprite GetEmbeddedIconNoCache(PluginLoader.PluginMetadata meta) { if (meta.Assembly == null) { return(null); } if (meta.Manifest.IconPath == null) { return(null); } try { return(UIUtilities.LoadSpriteRaw(UIUtilities.GetResource(meta.Assembly, meta.Manifest.IconPath))); } catch (Exception e) { Logger.log.Error($"Error loading icon for {meta.Name}"); Logger.log.Error(e); return(null); } }
/// <summary> /// Initializes the feature with the parameters provided in the definition. /// /// Note: When no parenthesis are provided, <paramref name="parameters"/> is an empty array. /// </summary> /// <remarks> /// This gets called BEFORE *your* `Init` method. /// /// Returning <see langword="false" /> does *not* prevent the plugin from being loaded. It simply prevents the feature from being used. /// </remarks> /// <param name="meta">the metadata of the plugin that is being prepared</param> /// <param name="parameters">the parameters passed to the feature definition, or null</param> /// <returns><see langword="true"/> if the feature is valid for the plugin, <see langword="false"/> otherwise</returns> public abstract bool Initialize(PluginLoader.PluginMetadata meta, string[] parameters);
// returns false with both outs null for no such feature internal static bool TryParseFeature(string featureString, PluginLoader.PluginMetadata plugin, out Feature feature, out Exception failException, out bool featureValid, out FeatureParse parsed, FeatureParse?preParsed = null) { failException = null; feature = null; featureValid = false; if (preParsed == null) { var builder = new StringBuilder(); string name = null; var parameters = new List <string>(); bool escape = false; int parens = 0; bool removeWhitespace = true; foreach (var chr in featureString) { if (escape) { builder.Append(chr); escape = false; } else { switch (chr) { case '\\': escape = true; break; case '(': parens++; if (parens != 1) { goto default; } removeWhitespace = true; name = builder.ToString(); builder.Clear(); break; case ')': parens--; if (parens != 0) { goto default; } goto case ','; case ',': if (parens > 1) { goto default; } parameters.Add(builder.ToString()); builder.Clear(); removeWhitespace = true; break; default: if (removeWhitespace && !char.IsWhiteSpace(chr)) { removeWhitespace = false; } if (!removeWhitespace) { builder.Append(chr); } break; } } } if (name == null) { name = builder.ToString(); } parsed = new FeatureParse(name, parameters.ToArray()); if (parens != 0) { failException = new Exception("Malformed feature definition"); return(false); } } else { parsed = preParsed.Value; } if (!featureTypes.TryGetValue(parsed.Name, out var featureType)) { return(false); } try { if (!(Activator.CreateInstance(featureType) is Feature aFeature)) { failException = new InvalidCastException("Feature type not a subtype of Feature"); return(false); } featureValid = aFeature.Initialize(plugin, parsed.Parameters); feature = aFeature; return(true); } catch (Exception e) { failException = e; return(false); } }
public void Init(IPALogger log, PluginLoader.PluginMetadata metadata) { Logger.Init(log); PluginVersion = metadata?.Version; }
public void Init(IPALogger logger, [Config.Prefer("json")] IConfigProvider cfgProvider, PluginLoader.PluginMetadata metadata) { Logger.log = logger; Configuration.Init(cfgProvider); if (metadata != null) { PluginVersion = metadata.Version; } }
/// <summary> /// Constructs a ModPrefs object for the provide plugin. /// </summary> /// <param name="plugin">the plugin to get the preferences file for</param> public ModPrefs(PluginLoader.PluginMetadata plugin) { _instance = new IniFile(Path.Combine(Environment.CurrentDirectory, "UserData", "ModPrefs", $"{plugin.Name}.ini")); }
public override bool Initialize(PluginLoader.PluginMetadata meta, string[] parameters) { return(meta.Id != null); }
public override bool Initialize(PluginLoader.PluginMetadata meta, string[] parameters) { // parameters should be (assembly qualified lookup type, [fully qualified type]:[method name]) // method should be static if (parameters.Length != 2) { InvalidMessage = "Incorrect number of parameters"; return(false); } RequireLoaded(meta); var methodParts = parameters[1].Split(':'); var type = Type.GetType(parameters[0], false); if (type == null) { InvalidMessage = $"Could not find type {parameters[0]}"; return(false); } Type getType; try { getType = meta.Assembly.GetType(methodParts[0]); } catch (ArgumentException) { InvalidMessage = $"Invalid type name {methodParts[0]}"; return(false); } catch (Exception e) when(e is FileNotFoundException || e is FileLoadException || e is BadImageFormatException) { string filename; switch (e) { case FileNotFoundException fn: filename = fn.FileName; goto hasFilename; case FileLoadException fl: filename = fl.FileName; goto hasFilename; case BadImageFormatException bi: filename = bi.FileName; hasFilename: InvalidMessage = $"Could not find {filename} while loading type"; break; default: InvalidMessage = $"Error while loading type: {e}"; break; } return(false); } MethodInfo method; try { method = getType.GetMethod(methodParts[1], BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new[] { typeof(object), typeof(ParameterInfo), typeof(PluginLoader.PluginMetadata) }, new ParameterModifier[0]); } catch (Exception e) { InvalidMessage = $"Error while loading type: {e}"; return(false); } if (method == null) { InvalidMessage = $"Could not find method {methodParts[1]} in type {methodParts[0]}"; return(false); } try { var del = (PluginInitInjector.InjectParameter)Delegate.CreateDelegate(typeof(PluginInitInjector.InjectParameter), null, method); PluginInitInjector.AddInjector(type, del); return(true); } catch (Exception e) { InvalidMessage = $"Error generated while creating delegate: {e}"; return(false); } }
public override bool Initialize(PluginLoader.PluginMetadata meta, string[] parameters) { Logger.features.Info($"{meta.Name}: {string.Join(" ", parameters)}"); return(true); }
public override bool BeforeLoad(PluginLoader.PluginMetadata plugin) { return(plugin != selfMeta); }
/// <summary> /// Called before a plugin is loaded. This should never throw an exception. An exception will abort the loading of the plugin with an error. /// </summary> /// <remarks> /// The assembly will still be loaded, but the plugin will not be constructed if this returns <see langword="false" />. /// Any features it defines, for example, will still be loaded. /// </remarks> /// <param name="plugin">the plugin about to be loaded</param> /// <returns>whether or not the plugin should be loaded</returns> public virtual bool BeforeLoad(PluginLoader.PluginMetadata plugin) => true;
/// <summary> /// Ensures a plugin's assembly is loaded. Do not use unless you need to. /// </summary> /// <param name="plugin">the plugin to ensure is loaded.</param> protected void RequireLoaded(PluginLoader.PluginMetadata plugin) => PluginLoader.Load(plugin);
public void Init(Sprite icon, string name, string version, string author, string description, PluginLoader.PluginMetadata updateInfo, PluginManifest.LinksObject links = null) { Icon = icon; Name = name; Version = version; Author = author; Description = description; UpdateInfo = updateInfo; if (rowTransformOriginal == null) { rowTransformOriginal = MenuButtonUI.Instance.GetPrivateField <RectTransform>("menuButtonsOriginal"); } // i also have no clue why this is necessary rectTransform.anchorMin = new Vector2(0f, 0f); rectTransform.anchorMax = new Vector2(0.5f, 1f); var go = new GameObject("Info View", typeof(RectTransform)); go.SetActive(false); go.AddComponent <RectMask2D>(); view = go.AddComponent <ModInfoView>(); var rt = view.transform as RectTransform; rt.SetParent(transform); rt.anchorMin = new Vector2(0f, 0f); rt.anchorMax = new Vector2(1f, 1f); rt.anchoredPosition = new Vector2(0f, 0); view.Init(this); go.SetActive(true); if (links != null) { rowTransform = Instantiate(rowTransformOriginal, rectTransform); rowTransform.anchorMin = new Vector2(0f, 0f); rowTransform.anchorMax = new Vector2(1f, .15f); rowTransform.anchoredPosition = new Vector2(-3.5f, -2f); foreach (Transform child in rowTransform) { child.name = string.Empty; Destroy(child.gameObject); } if (links.ProjectHome != null) { linkHomeButton = BeatSaberUI.CreateUIButton(rowTransform, "QuitButton", buttonText: "Home", onClick: () => Process.Start(links.ProjectHome.ToString())); linkHomeButton.GetComponentInChildren <HorizontalLayoutGroup>().padding = new RectOffset(6, 6, 0, 0); } if (links.ProjectSource != null) { linkSourceButton = BeatSaberUI.CreateUIButton(rowTransform, "QuitButton", buttonText: "Source", onClick: () => Process.Start(links.ProjectSource.ToString())); linkSourceButton.GetComponentInChildren <HorizontalLayoutGroup>().padding = new RectOffset(6, 6, 0, 0); } if (links.Donate != null) { linkDonateButton = BeatSaberUI.CreateUIButton(rowTransform, "QuitButton", buttonText: "Donate", onClick: () => Process.Start(links.Donate.ToString())); linkDonateButton.GetComponentInChildren <HorizontalLayoutGroup>().padding = new RectOffset(6, 6, 0, 0); } } }