From f7e14343f0bf157f7a694783d784c4c29c327f47 Mon Sep 17 00:00:00 2001
From: qqrz997 <156676353+qqrz997@users.noreply.github.com>
Date: Wed, 22 Jan 2025 12:56:06 +0000
Subject: [PATCH] Update templates
---
.../$safeprojectname$.csproj | 0
.../$safeprojectname$Controller.cs | 0
.../.template.config/template.json | 0
.../BSIPA Plugin (Core)/Directory.Build.props | 0
.../Directory.Build.targets | 0
.../BSIPA Plugin (Core)/Plugin.cs | 0
.../BSIPA Plugin (Core)/PluginConfig.cs | 0
.../Properties/AssemblyInfo.cs | 0
.../BSIPA Plugin (Core)/beat_saber.ico | Bin
.../BSIPA Plugin (Core)/manifest.json | 0
.../$safeprojectname$.csproj | 0
.../.template.config/template.json | 0
.../Configuration/PluginConfig.cs | 0
.../Directory.Build.props | 0
.../Directory.Build.targets | 0
.../$safeprojectname$FlowCoordinator.cs | 0
.../$safeprojectname$AppInstaller.cs | 0
.../$safeprojectname$GameInstaller.cs | 0
.../$safeprojectname$MenuInstaller.cs | 0
.../Managers/$safeprojectname$Manager.cs | 0
.../Plugin.cs | 0
.../UI/$safeprojectname$ViewController.cs | 0
.../UI/BSML/$safeprojectname$View.bsml | 0
.../beat_saber.ico | Bin
.../manifest.json | 0
.../.template.config/template.json | 83 +++++++++++++
.../BSIPA Plugin (Bare)/BarePlugin.csproj | 85 +++++++++++++
.../BSIPA Plugin (Bare)/Directory.Build.props | 33 ++++++
.../BSIPA Plugin (Bare)/Plugin.cs | 34 ++++++
.../$safeprojectname$.csproj.user | 7 --
.../.template.config/template.json | 83 +++++++++++++
.../BSIPA Plugin (UI)/Directory.Build.props | 34 ++++++
.../Menu/ExampleSettingsMenu.cs | 41 +++++++
.../Menu/SettingsMenuManager.cs | 39 ++++++
.../BSIPA Plugin (UI)/Menu/example.bsml | 7 ++
.../BSIPA Plugin (UI)/MenuPlugin.csproj | 89 ++++++++++++++
.../BSIPA Plugin (UI)/MenuPluginController.cs | 70 +++++++++++
projectTemplates/BSIPA Plugin (UI)/Plugin.cs | 45 +++++++
.../BSIPA Plugin (UI)/PluginConfig.cs | 40 +++++++
.../.template.config/template.json | 83 +++++++++++++
.../Directory.Build.props | 35 ++++++
.../ExampleController.cs | 58 +++++++++
.../Installers/AppInstaller.cs | 39 ++++++
.../Installers/MenuInstaller.cs | 29 +++++
.../Menu/ExampleSettingsMenu.cs | 40 +++++++
.../Menu/SettingsMenuManager.cs | 41 +++++++
.../Menu/example.bsml | 7 ++
.../BSIPA Plugin (Zenject-UI)/Plugin.cs | 44 +++++++
.../BSIPA Plugin (Zenject-UI)/PluginConfig.cs | 40 +++++++
.../ZenjectMenuPlugin.csproj | 112 ++++++++++++++++++
50 files changed, 1211 insertions(+), 7 deletions(-)
rename {projectTemplates => projectTemplates.old}/BSIPA Plugin (Core)/$safeprojectname$.csproj (100%)
rename {projectTemplates => projectTemplates.old}/BSIPA Plugin (Core)/$safeprojectname$Controller.cs (100%)
rename {projectTemplates => projectTemplates.old}/BSIPA Plugin (Core)/.template.config/template.json (100%)
rename {projectTemplates => projectTemplates.old}/BSIPA Plugin (Core)/Directory.Build.props (100%)
rename {projectTemplates => projectTemplates.old}/BSIPA Plugin (Core)/Directory.Build.targets (100%)
rename {projectTemplates => projectTemplates.old}/BSIPA Plugin (Core)/Plugin.cs (100%)
rename {projectTemplates => projectTemplates.old}/BSIPA Plugin (Core)/PluginConfig.cs (100%)
rename {projectTemplates => projectTemplates.old}/BSIPA Plugin (Core)/Properties/AssemblyInfo.cs (100%)
rename {projectTemplates => projectTemplates.old}/BSIPA Plugin (Core)/beat_saber.ico (100%)
rename {projectTemplates => projectTemplates.old}/BSIPA Plugin (Core)/manifest.json (100%)
rename {projectTemplates => projectTemplates.old}/BSIPA4 Plugin (Barebones Zenject Project)/$safeprojectname$.csproj (100%)
rename {projectTemplates => projectTemplates.old}/BSIPA4 Plugin (Barebones Zenject Project)/.template.config/template.json (100%)
rename {projectTemplates => projectTemplates.old}/BSIPA4 Plugin (Barebones Zenject Project)/Configuration/PluginConfig.cs (100%)
rename {projectTemplates => projectTemplates.old}/BSIPA4 Plugin (Barebones Zenject Project)/Directory.Build.props (100%)
rename {projectTemplates => projectTemplates.old}/BSIPA4 Plugin (Barebones Zenject Project)/Directory.Build.targets (100%)
rename {projectTemplates => projectTemplates.old}/BSIPA4 Plugin (Barebones Zenject Project)/FlowCoordinators/$safeprojectname$FlowCoordinator.cs (100%)
rename {projectTemplates => projectTemplates.old}/BSIPA4 Plugin (Barebones Zenject Project)/Installers/$safeprojectname$AppInstaller.cs (100%)
rename {projectTemplates => projectTemplates.old}/BSIPA4 Plugin (Barebones Zenject Project)/Installers/$safeprojectname$GameInstaller.cs (100%)
rename {projectTemplates => projectTemplates.old}/BSIPA4 Plugin (Barebones Zenject Project)/Installers/$safeprojectname$MenuInstaller.cs (100%)
rename {projectTemplates => projectTemplates.old}/BSIPA4 Plugin (Barebones Zenject Project)/Managers/$safeprojectname$Manager.cs (100%)
rename {projectTemplates => projectTemplates.old}/BSIPA4 Plugin (Barebones Zenject Project)/Plugin.cs (100%)
rename {projectTemplates => projectTemplates.old}/BSIPA4 Plugin (Barebones Zenject Project)/UI/$safeprojectname$ViewController.cs (100%)
rename {projectTemplates => projectTemplates.old}/BSIPA4 Plugin (Barebones Zenject Project)/UI/BSML/$safeprojectname$View.bsml (100%)
rename {projectTemplates => projectTemplates.old}/BSIPA4 Plugin (Barebones Zenject Project)/beat_saber.ico (100%)
rename {projectTemplates => projectTemplates.old}/BSIPA4 Plugin (Barebones Zenject Project)/manifest.json (100%)
create mode 100644 projectTemplates/BSIPA Plugin (Bare)/.template.config/template.json
create mode 100644 projectTemplates/BSIPA Plugin (Bare)/BarePlugin.csproj
create mode 100644 projectTemplates/BSIPA Plugin (Bare)/Directory.Build.props
create mode 100644 projectTemplates/BSIPA Plugin (Bare)/Plugin.cs
delete mode 100644 projectTemplates/BSIPA Plugin (Core)/$safeprojectname$.csproj.user
create mode 100644 projectTemplates/BSIPA Plugin (UI)/.template.config/template.json
create mode 100644 projectTemplates/BSIPA Plugin (UI)/Directory.Build.props
create mode 100644 projectTemplates/BSIPA Plugin (UI)/Menu/ExampleSettingsMenu.cs
create mode 100644 projectTemplates/BSIPA Plugin (UI)/Menu/SettingsMenuManager.cs
create mode 100644 projectTemplates/BSIPA Plugin (UI)/Menu/example.bsml
create mode 100644 projectTemplates/BSIPA Plugin (UI)/MenuPlugin.csproj
create mode 100644 projectTemplates/BSIPA Plugin (UI)/MenuPluginController.cs
create mode 100644 projectTemplates/BSIPA Plugin (UI)/Plugin.cs
create mode 100644 projectTemplates/BSIPA Plugin (UI)/PluginConfig.cs
create mode 100644 projectTemplates/BSIPA Plugin (Zenject-UI)/.template.config/template.json
create mode 100644 projectTemplates/BSIPA Plugin (Zenject-UI)/Directory.Build.props
create mode 100644 projectTemplates/BSIPA Plugin (Zenject-UI)/ExampleController.cs
create mode 100644 projectTemplates/BSIPA Plugin (Zenject-UI)/Installers/AppInstaller.cs
create mode 100644 projectTemplates/BSIPA Plugin (Zenject-UI)/Installers/MenuInstaller.cs
create mode 100644 projectTemplates/BSIPA Plugin (Zenject-UI)/Menu/ExampleSettingsMenu.cs
create mode 100644 projectTemplates/BSIPA Plugin (Zenject-UI)/Menu/SettingsMenuManager.cs
create mode 100644 projectTemplates/BSIPA Plugin (Zenject-UI)/Menu/example.bsml
create mode 100644 projectTemplates/BSIPA Plugin (Zenject-UI)/Plugin.cs
create mode 100644 projectTemplates/BSIPA Plugin (Zenject-UI)/PluginConfig.cs
create mode 100644 projectTemplates/BSIPA Plugin (Zenject-UI)/ZenjectMenuPlugin.csproj
diff --git a/projectTemplates/BSIPA Plugin (Core)/$safeprojectname$.csproj b/projectTemplates.old/BSIPA Plugin (Core)/$safeprojectname$.csproj
similarity index 100%
rename from projectTemplates/BSIPA Plugin (Core)/$safeprojectname$.csproj
rename to projectTemplates.old/BSIPA Plugin (Core)/$safeprojectname$.csproj
diff --git a/projectTemplates/BSIPA Plugin (Core)/$safeprojectname$Controller.cs b/projectTemplates.old/BSIPA Plugin (Core)/$safeprojectname$Controller.cs
similarity index 100%
rename from projectTemplates/BSIPA Plugin (Core)/$safeprojectname$Controller.cs
rename to projectTemplates.old/BSIPA Plugin (Core)/$safeprojectname$Controller.cs
diff --git a/projectTemplates/BSIPA Plugin (Core)/.template.config/template.json b/projectTemplates.old/BSIPA Plugin (Core)/.template.config/template.json
similarity index 100%
rename from projectTemplates/BSIPA Plugin (Core)/.template.config/template.json
rename to projectTemplates.old/BSIPA Plugin (Core)/.template.config/template.json
diff --git a/projectTemplates/BSIPA Plugin (Core)/Directory.Build.props b/projectTemplates.old/BSIPA Plugin (Core)/Directory.Build.props
similarity index 100%
rename from projectTemplates/BSIPA Plugin (Core)/Directory.Build.props
rename to projectTemplates.old/BSIPA Plugin (Core)/Directory.Build.props
diff --git a/projectTemplates/BSIPA Plugin (Core)/Directory.Build.targets b/projectTemplates.old/BSIPA Plugin (Core)/Directory.Build.targets
similarity index 100%
rename from projectTemplates/BSIPA Plugin (Core)/Directory.Build.targets
rename to projectTemplates.old/BSIPA Plugin (Core)/Directory.Build.targets
diff --git a/projectTemplates/BSIPA Plugin (Core)/Plugin.cs b/projectTemplates.old/BSIPA Plugin (Core)/Plugin.cs
similarity index 100%
rename from projectTemplates/BSIPA Plugin (Core)/Plugin.cs
rename to projectTemplates.old/BSIPA Plugin (Core)/Plugin.cs
diff --git a/projectTemplates/BSIPA Plugin (Core)/PluginConfig.cs b/projectTemplates.old/BSIPA Plugin (Core)/PluginConfig.cs
similarity index 100%
rename from projectTemplates/BSIPA Plugin (Core)/PluginConfig.cs
rename to projectTemplates.old/BSIPA Plugin (Core)/PluginConfig.cs
diff --git a/projectTemplates/BSIPA Plugin (Core)/Properties/AssemblyInfo.cs b/projectTemplates.old/BSIPA Plugin (Core)/Properties/AssemblyInfo.cs
similarity index 100%
rename from projectTemplates/BSIPA Plugin (Core)/Properties/AssemblyInfo.cs
rename to projectTemplates.old/BSIPA Plugin (Core)/Properties/AssemblyInfo.cs
diff --git a/projectTemplates/BSIPA Plugin (Core)/beat_saber.ico b/projectTemplates.old/BSIPA Plugin (Core)/beat_saber.ico
similarity index 100%
rename from projectTemplates/BSIPA Plugin (Core)/beat_saber.ico
rename to projectTemplates.old/BSIPA Plugin (Core)/beat_saber.ico
diff --git a/projectTemplates/BSIPA Plugin (Core)/manifest.json b/projectTemplates.old/BSIPA Plugin (Core)/manifest.json
similarity index 100%
rename from projectTemplates/BSIPA Plugin (Core)/manifest.json
rename to projectTemplates.old/BSIPA Plugin (Core)/manifest.json
diff --git a/projectTemplates/BSIPA4 Plugin (Barebones Zenject Project)/$safeprojectname$.csproj b/projectTemplates.old/BSIPA4 Plugin (Barebones Zenject Project)/$safeprojectname$.csproj
similarity index 100%
rename from projectTemplates/BSIPA4 Plugin (Barebones Zenject Project)/$safeprojectname$.csproj
rename to projectTemplates.old/BSIPA4 Plugin (Barebones Zenject Project)/$safeprojectname$.csproj
diff --git a/projectTemplates/BSIPA4 Plugin (Barebones Zenject Project)/.template.config/template.json b/projectTemplates.old/BSIPA4 Plugin (Barebones Zenject Project)/.template.config/template.json
similarity index 100%
rename from projectTemplates/BSIPA4 Plugin (Barebones Zenject Project)/.template.config/template.json
rename to projectTemplates.old/BSIPA4 Plugin (Barebones Zenject Project)/.template.config/template.json
diff --git a/projectTemplates/BSIPA4 Plugin (Barebones Zenject Project)/Configuration/PluginConfig.cs b/projectTemplates.old/BSIPA4 Plugin (Barebones Zenject Project)/Configuration/PluginConfig.cs
similarity index 100%
rename from projectTemplates/BSIPA4 Plugin (Barebones Zenject Project)/Configuration/PluginConfig.cs
rename to projectTemplates.old/BSIPA4 Plugin (Barebones Zenject Project)/Configuration/PluginConfig.cs
diff --git a/projectTemplates/BSIPA4 Plugin (Barebones Zenject Project)/Directory.Build.props b/projectTemplates.old/BSIPA4 Plugin (Barebones Zenject Project)/Directory.Build.props
similarity index 100%
rename from projectTemplates/BSIPA4 Plugin (Barebones Zenject Project)/Directory.Build.props
rename to projectTemplates.old/BSIPA4 Plugin (Barebones Zenject Project)/Directory.Build.props
diff --git a/projectTemplates/BSIPA4 Plugin (Barebones Zenject Project)/Directory.Build.targets b/projectTemplates.old/BSIPA4 Plugin (Barebones Zenject Project)/Directory.Build.targets
similarity index 100%
rename from projectTemplates/BSIPA4 Plugin (Barebones Zenject Project)/Directory.Build.targets
rename to projectTemplates.old/BSIPA4 Plugin (Barebones Zenject Project)/Directory.Build.targets
diff --git a/projectTemplates/BSIPA4 Plugin (Barebones Zenject Project)/FlowCoordinators/$safeprojectname$FlowCoordinator.cs b/projectTemplates.old/BSIPA4 Plugin (Barebones Zenject Project)/FlowCoordinators/$safeprojectname$FlowCoordinator.cs
similarity index 100%
rename from projectTemplates/BSIPA4 Plugin (Barebones Zenject Project)/FlowCoordinators/$safeprojectname$FlowCoordinator.cs
rename to projectTemplates.old/BSIPA4 Plugin (Barebones Zenject Project)/FlowCoordinators/$safeprojectname$FlowCoordinator.cs
diff --git a/projectTemplates/BSIPA4 Plugin (Barebones Zenject Project)/Installers/$safeprojectname$AppInstaller.cs b/projectTemplates.old/BSIPA4 Plugin (Barebones Zenject Project)/Installers/$safeprojectname$AppInstaller.cs
similarity index 100%
rename from projectTemplates/BSIPA4 Plugin (Barebones Zenject Project)/Installers/$safeprojectname$AppInstaller.cs
rename to projectTemplates.old/BSIPA4 Plugin (Barebones Zenject Project)/Installers/$safeprojectname$AppInstaller.cs
diff --git a/projectTemplates/BSIPA4 Plugin (Barebones Zenject Project)/Installers/$safeprojectname$GameInstaller.cs b/projectTemplates.old/BSIPA4 Plugin (Barebones Zenject Project)/Installers/$safeprojectname$GameInstaller.cs
similarity index 100%
rename from projectTemplates/BSIPA4 Plugin (Barebones Zenject Project)/Installers/$safeprojectname$GameInstaller.cs
rename to projectTemplates.old/BSIPA4 Plugin (Barebones Zenject Project)/Installers/$safeprojectname$GameInstaller.cs
diff --git a/projectTemplates/BSIPA4 Plugin (Barebones Zenject Project)/Installers/$safeprojectname$MenuInstaller.cs b/projectTemplates.old/BSIPA4 Plugin (Barebones Zenject Project)/Installers/$safeprojectname$MenuInstaller.cs
similarity index 100%
rename from projectTemplates/BSIPA4 Plugin (Barebones Zenject Project)/Installers/$safeprojectname$MenuInstaller.cs
rename to projectTemplates.old/BSIPA4 Plugin (Barebones Zenject Project)/Installers/$safeprojectname$MenuInstaller.cs
diff --git a/projectTemplates/BSIPA4 Plugin (Barebones Zenject Project)/Managers/$safeprojectname$Manager.cs b/projectTemplates.old/BSIPA4 Plugin (Barebones Zenject Project)/Managers/$safeprojectname$Manager.cs
similarity index 100%
rename from projectTemplates/BSIPA4 Plugin (Barebones Zenject Project)/Managers/$safeprojectname$Manager.cs
rename to projectTemplates.old/BSIPA4 Plugin (Barebones Zenject Project)/Managers/$safeprojectname$Manager.cs
diff --git a/projectTemplates/BSIPA4 Plugin (Barebones Zenject Project)/Plugin.cs b/projectTemplates.old/BSIPA4 Plugin (Barebones Zenject Project)/Plugin.cs
similarity index 100%
rename from projectTemplates/BSIPA4 Plugin (Barebones Zenject Project)/Plugin.cs
rename to projectTemplates.old/BSIPA4 Plugin (Barebones Zenject Project)/Plugin.cs
diff --git a/projectTemplates/BSIPA4 Plugin (Barebones Zenject Project)/UI/$safeprojectname$ViewController.cs b/projectTemplates.old/BSIPA4 Plugin (Barebones Zenject Project)/UI/$safeprojectname$ViewController.cs
similarity index 100%
rename from projectTemplates/BSIPA4 Plugin (Barebones Zenject Project)/UI/$safeprojectname$ViewController.cs
rename to projectTemplates.old/BSIPA4 Plugin (Barebones Zenject Project)/UI/$safeprojectname$ViewController.cs
diff --git a/projectTemplates/BSIPA4 Plugin (Barebones Zenject Project)/UI/BSML/$safeprojectname$View.bsml b/projectTemplates.old/BSIPA4 Plugin (Barebones Zenject Project)/UI/BSML/$safeprojectname$View.bsml
similarity index 100%
rename from projectTemplates/BSIPA4 Plugin (Barebones Zenject Project)/UI/BSML/$safeprojectname$View.bsml
rename to projectTemplates.old/BSIPA4 Plugin (Barebones Zenject Project)/UI/BSML/$safeprojectname$View.bsml
diff --git a/projectTemplates/BSIPA4 Plugin (Barebones Zenject Project)/beat_saber.ico b/projectTemplates.old/BSIPA4 Plugin (Barebones Zenject Project)/beat_saber.ico
similarity index 100%
rename from projectTemplates/BSIPA4 Plugin (Barebones Zenject Project)/beat_saber.ico
rename to projectTemplates.old/BSIPA4 Plugin (Barebones Zenject Project)/beat_saber.ico
diff --git a/projectTemplates/BSIPA4 Plugin (Barebones Zenject Project)/manifest.json b/projectTemplates.old/BSIPA4 Plugin (Barebones Zenject Project)/manifest.json
similarity index 100%
rename from projectTemplates/BSIPA4 Plugin (Barebones Zenject Project)/manifest.json
rename to projectTemplates.old/BSIPA4 Plugin (Barebones Zenject Project)/manifest.json
diff --git a/projectTemplates/BSIPA Plugin (Bare)/.template.config/template.json b/projectTemplates/BSIPA Plugin (Bare)/.template.config/template.json
new file mode 100644
index 0000000..fd59694
--- /dev/null
+++ b/projectTemplates/BSIPA Plugin (Bare)/.template.config/template.json
@@ -0,0 +1,83 @@
+{
+ "$schema": "https://json.schemastore.org/template",
+ "author": "qqrz997",
+ "classifications": [
+ "Common",
+ "Library"
+ ],
+ "identity": "BSIPA.Plugin.Bare",
+ "name": "BSIPA Plugin (Bare)",
+ "defaultName": "BeatSaberPlugin",
+ "description": "A bare-minimum template for a new Beat Saber IPA mod.",
+ "shortName": "bsbare",
+ "sourceName": "BarePlugin",
+ "tags": {
+ "language": "C#",
+ "type": "project",
+ "platform": ".NET"
+ },
+ "preferNameDirectory": true,
+ "symbols": {
+ "ModVersion": {
+ "type": "parameter",
+ "description": "The version of the mod. Must be of format major.minor.patch.",
+ "datatype": "text",
+ "replaces": "{ModVersion}",
+ "defaultValue": "0.0.1",
+ "displayName": "Mod Version"
+ },
+ "ModAuthor": {
+ "type": "parameter",
+ "description": "The name of who is developing the mod.",
+ "datatype": "text",
+ "replaces": "{ModAuthor}",
+ "displayName": "Author",
+ "defaultValue": ""
+ },
+ "ModDescription": {
+ "type": "parameter",
+ "description": "A short sentence describing the mod's features.",
+ "datatype": "text",
+ "replaces": "{ModDescription}",
+ "displayName": "Description",
+ "defaultValue": ""
+ },
+ "GameVersion": {
+ "type": "parameter",
+ "description": "Version of the game you are developing for.",
+ "datatype": "text",
+ "replaces": "{GameVersion}",
+ "displayName": "Game Version",
+ "defaultValue": "1.40.0"
+ },
+ "Nullable": {
+ "type": "parameter",
+ "description": "Use nullable reference types. (Recommended)",
+ "datatype": "bool",
+ "replaces": "{Nullable}",
+ "defaultValue": "true"
+ },
+ "EnableHints": {
+ "type": "parameter",
+ "description": "Includes code comments that provide helpful information.",
+ "datatype": "bool",
+ "displayName": "Enable Hints",
+ "defaultValue": "true"
+ }
+ },
+ "primaryOutputs": [
+ {"path": "Plugin.cs" }
+ ],
+ "postActions": [
+ {
+ "condition": "(HostIdentifier != \"dotnetcli\")",
+ "description": "Opens Plugin.cs in the editor",
+ "manualInstructions": [ ],
+ "actionId": "84C0DA21-51C8-4541-9940-6CA19AF04EE6",
+ "args": {
+ "files": "0"
+ },
+ "continueOnError": true
+ }
+ ]
+}
\ No newline at end of file
diff --git a/projectTemplates/BSIPA Plugin (Bare)/BarePlugin.csproj b/projectTemplates/BSIPA Plugin (Bare)/BarePlugin.csproj
new file mode 100644
index 0000000..2c71418
--- /dev/null
+++ b/projectTemplates/BSIPA Plugin (Bare)/BarePlugin.csproj
@@ -0,0 +1,85 @@
+
+
+
+
+
+ net472
+
+
+
+
+ latest
+
+ enable
+
+ disable
+
+ true
+ true
+ $(BeatSaberDir)\Beat Saber_Data\Managed
+ false
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
+
+ $(BeatSaberDir)\Beat Saber_Data\Managed\BeatSaber.ViewSystem.dll
+ false
+
+
+ $(BeatSaberDir)\Plugins\BSML.dll
+ false
+
+
+ $(BeatSaberDir)\Libs\Hive.Versioning.dll
+ false
+
+
+ $(BeatSaberDir)\Beat Saber_Data\Managed\IPA.Loader.dll
+ false
+
+
+ $(BeatSaberDir)\Beat Saber_Data\Managed\Main.dll
+ false
+
+
+
+
+
+
+ $(BeatSaberDir)\Beat Saber_Data\Managed\Unity.TextMeshPro.dll
+ false
+
+
+ $(BeatSaberDir)\Beat Saber_Data\Managed\UnityEngine.dll
+ false
+
+
+ $(BeatSaberDir)\Beat Saber_Data\Managed\UnityEngine.CoreModule.dll
+ false
+
+
+ $(BeatSaberDir)\Beat Saber_Data\Managed\UnityEngine.UI.dll
+ False
+
+
+ $(BeatSaberDir)\Beat Saber_Data\Managed\UnityEngine.UIElementsModule.dll
+ False
+
+
+ $(BeatSaberDir)\Beat Saber_Data\Managed\UnityEngine.UIModule.dll
+ False
+
+
+
+
\ No newline at end of file
diff --git a/projectTemplates/BSIPA Plugin (Bare)/Directory.Build.props b/projectTemplates/BSIPA Plugin (Bare)/Directory.Build.props
new file mode 100644
index 0000000..0f69e3e
--- /dev/null
+++ b/projectTemplates/BSIPA Plugin (Bare)/Directory.Build.props
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+ BarePlugin
+ BarePlugin
+ {ModAuthor}
+ {ModVersion}
+ {GameVersion}
+ {ModDescription}
+
+
+
+
+
+
+
+
+
+
+
+
+ BSIPA
+ true
+
+
+
+ true
+
+
+
\ No newline at end of file
diff --git a/projectTemplates/BSIPA Plugin (Bare)/Plugin.cs b/projectTemplates/BSIPA Plugin (Bare)/Plugin.cs
new file mode 100644
index 0000000..5f31b31
--- /dev/null
+++ b/projectTemplates/BSIPA Plugin (Bare)/Plugin.cs
@@ -0,0 +1,34 @@
+using IPA;
+using IPA.Loader;
+using IpaLogger = IPA.Logging.Logger;
+
+namespace BarePlugin;
+
+[Plugin(RuntimeOptions.DynamicInit)]
+internal class Plugin
+{
+ internal static IpaLogger Log { get; private set; } = null!;
+#if (EnableHints)
+ // Methods with [Init] are called when the plugin is first loaded by IPA.
+ // All the parameters are provided by IPA and are optional.
+ // The constructor is called before any method with [Init]. Only use [Init] with one constructor.
+#endif
+ [Init]
+ public Plugin(IpaLogger ipaLogger, PluginMetadata pluginMetadata)
+ {
+ Log = ipaLogger;
+ Log.Info($"{pluginMetadata.Name} {pluginMetadata.HVersion} initialized.");
+ }
+
+ [OnStart]
+ public void OnApplicationStart()
+ {
+ Log.Debug("OnApplicationStart");
+ }
+
+ [OnExit]
+ public void OnApplicationQuit()
+ {
+ Log.Debug("OnApplicationQuit");
+ }
+}
\ No newline at end of file
diff --git a/projectTemplates/BSIPA Plugin (Core)/$safeprojectname$.csproj.user b/projectTemplates/BSIPA Plugin (Core)/$safeprojectname$.csproj.user
deleted file mode 100644
index 70913ad..0000000
--- a/projectTemplates/BSIPA Plugin (Core)/$safeprojectname$.csproj.user
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
- $SomeBeatSaberDir$
-
-
\ No newline at end of file
diff --git a/projectTemplates/BSIPA Plugin (UI)/.template.config/template.json b/projectTemplates/BSIPA Plugin (UI)/.template.config/template.json
new file mode 100644
index 0000000..aa3abb9
--- /dev/null
+++ b/projectTemplates/BSIPA Plugin (UI)/.template.config/template.json
@@ -0,0 +1,83 @@
+{
+ "$schema": "https://json.schemastore.org/template",
+ "author": "qqrz997",
+ "classifications": [
+ "Common",
+ "Library"
+ ],
+ "identity": "BSIPA.Plugin.UI",
+ "name": "BSIPA Plugin (UI)",
+ "defaultName": "BeatSaberPlugin",
+ "description": "A template for a new Beat Saber IPA mod with a basic UI setup using BeatSaberMarkupLanguage.",
+ "shortName": "bsui",
+ "sourceName": "MenuPlugin",
+ "tags": {
+ "language": "C#",
+ "type": "project",
+ "platform": ".NET"
+ },
+ "preferNameDirectory": true,
+ "symbols": {
+ "ModVersion": {
+ "type": "parameter",
+ "description": "The version of the mod. Must be of format major.minor.patch.",
+ "datatype": "text",
+ "replaces": "{ModVersion}",
+ "defaultValue": "0.0.1",
+ "displayName": "Mod Version"
+ },
+ "ModAuthor": {
+ "type": "parameter",
+ "description": "The name of who is developing the mod.",
+ "datatype": "text",
+ "replaces": "{ModAuthor}",
+ "displayName": "Author",
+ "defaultValue": ""
+ },
+ "ModDescription": {
+ "type": "parameter",
+ "description": "A short sentence describing the mod's features.",
+ "datatype": "text",
+ "replaces": "{ModDescription}",
+ "displayName": "Description",
+ "defaultValue": ""
+ },
+ "GameVersion": {
+ "type": "parameter",
+ "description": "Version of the game you are developing for.",
+ "datatype": "text",
+ "replaces": "{GameVersion}",
+ "displayName": "Game Version",
+ "defaultValue": "1.40.0"
+ },
+ "Nullable": {
+ "type": "parameter",
+ "description": "Use nullable reference types. (Recommended)",
+ "datatype": "bool",
+ "replaces": "{Nullable}",
+ "defaultValue": "true"
+ },
+ "EnableHints": {
+ "type": "parameter",
+ "description": "Includes code comments that provide helpful information.",
+ "datatype": "bool",
+ "displayName": "Enable Hints",
+ "defaultValue": "true"
+ }
+ },
+ "primaryOutputs": [
+ {"path": "Plugin.cs" }
+ ],
+ "postActions": [
+ {
+ "condition": "(HostIdentifier != \"dotnetcli\")",
+ "description": "Opens Plugin.cs in the editor",
+ "manualInstructions": [ ],
+ "actionId": "84C0DA21-51C8-4541-9940-6CA19AF04EE6",
+ "args": {
+ "files": "0"
+ },
+ "continueOnError": true
+ }
+ ]
+}
\ No newline at end of file
diff --git a/projectTemplates/BSIPA Plugin (UI)/Directory.Build.props b/projectTemplates/BSIPA Plugin (UI)/Directory.Build.props
new file mode 100644
index 0000000..b4890e0
--- /dev/null
+++ b/projectTemplates/BSIPA Plugin (UI)/Directory.Build.props
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+ MenuPlugin
+ MenuPlugin
+ {ModAuthor}
+ {ModVersion}
+ {GameVersion}
+ {ModDescription}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ BSIPA
+ true
+
+
+
+ true
+
+
+
\ No newline at end of file
diff --git a/projectTemplates/BSIPA Plugin (UI)/Menu/ExampleSettingsMenu.cs b/projectTemplates/BSIPA Plugin (UI)/Menu/ExampleSettingsMenu.cs
new file mode 100644
index 0000000..e7fd07c
--- /dev/null
+++ b/projectTemplates/BSIPA Plugin (UI)/Menu/ExampleSettingsMenu.cs
@@ -0,0 +1,41 @@
+using BeatSaberMarkupLanguage.Attributes;
+using HMUI;
+using TMPro;
+using UnityEngine;
+
+namespace MenuPlugin.Menu;
+#if (EnableHints)
+// This class is for managing the BSML resource and interact with the UI object in game.
+// To see more about components read the BSML docs. https://monkeymanboy.github.io/BSML-Docs/
+#endif
+internal class ExampleSettingsMenu : MonoBehaviour
+{
+#if (EnableHints)
+ // [UIComponent] will get a specified component from the BSML object with the matching id
+#endif
+ [UIComponent("example-image")]
+ private readonly ImageView exampleImage = null!;
+
+ [UIComponent("example-text")]
+ private readonly TextMeshProUGUI exampleText = null!;
+
+#if (EnableHints)
+ // The #post-parse event is provided by BSML. This action is invoked after BSML has parsed this object and
+ // all [UIComponent] and [UIObject] members have been populated. Any initialization logic for the menu should
+ // be done in here, rather than in Unity's Awake or Start events.
+#endif
+ [UIAction("#post-parse")]
+ private void PostParse()
+ {
+ Plugin.Log.Debug($"{name} parsed");
+ }
+#if (EnableHints)
+ // [UIAction] will be used by UI elements like buttons to invoke methods such as the one here.
+#endif
+ [UIAction("example-action")]
+ private void ExampleAction()
+ {
+ exampleImage.color = Color.white;
+ exampleText.text = "Hello World!";
+ }
+}
\ No newline at end of file
diff --git a/projectTemplates/BSIPA Plugin (UI)/Menu/SettingsMenuManager.cs b/projectTemplates/BSIPA Plugin (UI)/Menu/SettingsMenuManager.cs
new file mode 100644
index 0000000..bf02858
--- /dev/null
+++ b/projectTemplates/BSIPA Plugin (UI)/Menu/SettingsMenuManager.cs
@@ -0,0 +1,39 @@
+using BeatSaberMarkupLanguage.Settings;
+using UnityEngine;
+
+namespace MenuPlugin.Menu;
+
+internal static class SettingsMenuManager
+{
+#if (Nullable)
+ private static ExampleSettingsMenu? Instance { get; set; }
+#else
+ private static ExampleSettingsMenu Instance { get; set; }
+#endif
+
+ private const string MenuName = nameof(MenuPlugin);
+ private const string ResourcePath = nameof(MenuPlugin) + ".Menu.example.bsml";
+#if (EnableHints)
+ ///
+ /// Adds a custom menu in the Mod Settings section of the main menu.
+ /// This should only be called when the main menu is active.
+ ///
+#endif
+ public static void AddSettingsMenu()
+ {
+ if (Instance == null)
+ {
+ Instance = new GameObject(nameof(ExampleSettingsMenu)).AddComponent();
+ Object.DontDestroyOnLoad(Instance.gameObject);
+ }
+
+ RemoveSettingsMenu();
+
+ BSMLSettings.Instance.AddSettingsMenu(MenuName, ResourcePath, Instance);
+ }
+
+ public static void RemoveSettingsMenu()
+ {
+ BSMLSettings.Instance.RemoveSettingsMenu(Instance);
+ }
+}
\ No newline at end of file
diff --git a/projectTemplates/BSIPA Plugin (UI)/Menu/example.bsml b/projectTemplates/BSIPA Plugin (UI)/Menu/example.bsml
new file mode 100644
index 0000000..20f06b3
--- /dev/null
+++ b/projectTemplates/BSIPA Plugin (UI)/Menu/example.bsml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/projectTemplates/BSIPA Plugin (UI)/MenuPlugin.csproj b/projectTemplates/BSIPA Plugin (UI)/MenuPlugin.csproj
new file mode 100644
index 0000000..f09033f
--- /dev/null
+++ b/projectTemplates/BSIPA Plugin (UI)/MenuPlugin.csproj
@@ -0,0 +1,89 @@
+
+
+
+
+
+ net472
+
+
+
+
+ latest
+
+ enable
+
+ disable
+
+ true
+ true
+ $(BeatSaberDir)\Beat Saber_Data\Managed
+ false
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(BeatSaberDir)\Beat Saber_Data\Managed\BeatSaber.ViewSystem.dll
+ false
+
+
+ $(BeatSaberDir)\Plugins\BSML.dll
+ false
+
+
+ $(BeatSaberDir)\Libs\Hive.Versioning.dll
+ false
+
+
+ $(BeatSaberDir)\Beat Saber_Data\Managed\IPA.Loader.dll
+ false
+
+
+ $(BeatSaberDir)\Beat Saber_Data\Managed\Main.dll
+ false
+
+
+
+
+
+
+ $(BeatSaberDir)\Beat Saber_Data\Managed\Unity.TextMeshPro.dll
+ false
+
+
+ $(BeatSaberDir)\Beat Saber_Data\Managed\UnityEngine.dll
+ false
+
+
+ $(BeatSaberDir)\Beat Saber_Data\Managed\UnityEngine.CoreModule.dll
+ false
+
+
+ $(BeatSaberDir)\Beat Saber_Data\Managed\UnityEngine.UI.dll
+ False
+
+
+ $(BeatSaberDir)\Beat Saber_Data\Managed\UnityEngine.UIElementsModule.dll
+ False
+
+
+ $(BeatSaberDir)\Beat Saber_Data\Managed\UnityEngine.UIModule.dll
+ False
+
+
+
+
\ No newline at end of file
diff --git a/projectTemplates/BSIPA Plugin (UI)/MenuPluginController.cs b/projectTemplates/BSIPA Plugin (UI)/MenuPluginController.cs
new file mode 100644
index 0000000..4c39387
--- /dev/null
+++ b/projectTemplates/BSIPA Plugin (UI)/MenuPluginController.cs
@@ -0,0 +1,70 @@
+using BeatSaberMarkupLanguage.Util;
+using MenuPlugin.Menu;
+using UnityEngine;
+
+namespace MenuPlugin;
+#if (EnableHints)
+// MonoBehaviours are scripts added to in-game GameObjects which execute code during runtime.
+// For a full list of Messages a MonoBehaviour can receive from the game, refer to the Unity documentation.
+// https://docs.unity3d.com/ScriptReference/MonoBehaviour.html
+#endif
+internal class MenuPluginController : MonoBehaviour
+{
+#if (Nullable)
+ private static MenuPluginController? Instance { get; set; }
+#else
+ private static MenuPluginController Instance { get; set; }
+#endif
+#if (EnableHints)
+ ///
+ /// Called a single time by Unity when this script is created.
+ ///
+#endif
+ private void Awake()
+ {
+#if (EnableHints)
+ // For this particular MonoBehaviour, we only want one instance to exist at any time.
+ // Store a reference to it in a static property and destroy any that are created while one already exists.
+#endif
+ if (Instance != null)
+ {
+ DestroyImmediate(this);
+ return;
+ }
+
+ DontDestroyOnLoad(this); // Don't destroy this object on scene changes
+ Instance = this;
+#if (EnableHints)
+ // Invoked when the main menu scene loads, or loads fresh after applying settings.
+ // This is important for initializing objects in the menu, namely UI objects.
+#endif
+ MainMenuAwaiter.MainMenuInitializing += SettingsMenuManager.AddSettingsMenu;
+ }
+#if (EnableHints)
+ ///
+ /// Called a single time by Unity on the first frame the script is enabled.
+ ///
+#endif
+ private void Start()
+ {
+ Plugin.Log.Debug($"{name} started");
+ }
+#if (EnableHints)
+ ///
+ /// Called a single time by Unity when the script is being destroyed.
+ ///
+#endif
+ private void OnDestroy()
+ {
+ Plugin.Log.Debug($"{name} destroyed");
+ MainMenuAwaiter.MainMenuInitializing -= SettingsMenuManager.AddSettingsMenu;
+
+ if (Instance == this)
+ {
+#if (EnableHints)
+ // This MonoBehaviour is being destroyed, so set the static instance property to null.
+#endif
+ Instance = null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/projectTemplates/BSIPA Plugin (UI)/Plugin.cs b/projectTemplates/BSIPA Plugin (UI)/Plugin.cs
new file mode 100644
index 0000000..c10d3f8
--- /dev/null
+++ b/projectTemplates/BSIPA Plugin (UI)/Plugin.cs
@@ -0,0 +1,45 @@
+using IPA;
+using IPA.Config.Stores;
+using IPA.Loader;
+using UnityEngine;
+using IpaLogger = IPA.Logging.Logger;
+using IpaConfig = IPA.Config.Config;
+
+namespace MenuPlugin;
+
+[Plugin(RuntimeOptions.DynamicInit)]
+internal class Plugin
+{
+ internal static IpaLogger Log { get; private set; } = null!;
+ internal static PluginConfig Config { get; private set; } = null!;
+
+#if (EnableHints)
+ // Methods with [Init] are called when the plugin is first loaded by IPA.
+ // All the parameters are provided by IPA and are optional.
+ // The constructor is called before any method with [Init]. Only use [Init] with one constructor.
+#endif
+ [Init]
+ public Plugin(IpaLogger ipaLogger, IpaConfig ipaConfig, PluginMetadata pluginMetadata)
+ {
+ Log = ipaLogger;
+#if (EnableHints)
+ // Creates an instance of PluginConfig used by IPA to load and store config values
+#endif
+ Config = ipaConfig.Generated();
+
+ Log.Info($"{pluginMetadata.Name} {pluginMetadata.HVersion} initialized.");
+ }
+
+ [OnStart]
+ public void OnApplicationStart()
+ {
+ Log.Debug("OnApplicationStart");
+ new GameObject("MenuPluginController").AddComponent();
+ }
+
+ [OnExit]
+ public void OnApplicationQuit()
+ {
+ Log.Debug("OnApplicationQuit");
+ }
+}
\ No newline at end of file
diff --git a/projectTemplates/BSIPA Plugin (UI)/PluginConfig.cs b/projectTemplates/BSIPA Plugin (UI)/PluginConfig.cs
new file mode 100644
index 0000000..53b4541
--- /dev/null
+++ b/projectTemplates/BSIPA Plugin (UI)/PluginConfig.cs
@@ -0,0 +1,40 @@
+using System.Runtime.CompilerServices;
+using IPA.Config.Stores;
+
+[assembly: InternalsVisibleTo(GeneratedStore.AssemblyVisibilityTarget)]
+namespace MenuPlugin;
+
+internal class PluginConfig
+{
+#if (EnableHints)
+ // Members must be 'virtual' if you want BSIPA to detect a value change and save the config automatically
+ // You can assign a default value to be used when the config is first created by assigning one after '='
+ // examples:
+#endif
+ // public virtual bool FeatureEnabled { get; set; } = true;
+ // public virtual int NumValue { get; set; } = 42;
+ // public virtual Color TheColor { get; set; } = new Color(0.12f, 0.34f, 0.56f);
+
+#if (EnableHints)
+ /*
+ ///
+ /// This is called whenever BSIPA reads the config from disk (including when file changes are detected).
+ ///
+ public virtual void OnReload() { }
+
+ ///
+ /// Call this to force BSIPA to update the config file. This is also called by BSIPA if it detects the file was modified.
+ ///
+ public virtual void Changed() { }
+
+ ///
+ /// Call this to have BSIPA copy the values from into this config.
+ ///
+ public virtual void CopyFrom(PluginConfig other) { }
+ */
+#else
+ // public virtual void OnReload() { }
+ // public virtual void Changed() { }
+ // public virtual void CopyFrom(PluginConfig other) { }
+#endif
+}
\ No newline at end of file
diff --git a/projectTemplates/BSIPA Plugin (Zenject-UI)/.template.config/template.json b/projectTemplates/BSIPA Plugin (Zenject-UI)/.template.config/template.json
new file mode 100644
index 0000000..53cd925
--- /dev/null
+++ b/projectTemplates/BSIPA Plugin (Zenject-UI)/.template.config/template.json
@@ -0,0 +1,83 @@
+{
+ "$schema": "https://json.schemastore.org/template",
+ "author": "qqrz997",
+ "classifications": [
+ "Common",
+ "Library"
+ ],
+ "identity": "BSIPA.Plugin.Zenject-UI",
+ "name": "BSIPA Plugin (Zenject-UI)",
+ "defaultName": "BeatSaberPlugin",
+ "description": "A template for a new Beat Saber IPA mod with a basic Zenject and UI setup using SiraUtil and BeatSaberMarkupLanguage.",
+ "shortName": "bszenjectui",
+ "sourceName": "ZenjectMenuPlugin",
+ "tags": {
+ "language": "C#",
+ "type": "project",
+ "platform": ".NET"
+ },
+ "preferNameDirectory": true,
+ "symbols": {
+ "ModVersion": {
+ "type": "parameter",
+ "description": "The version of the mod. Must be of format major.minor.patch.",
+ "datatype": "text",
+ "replaces": "{ModVersion}",
+ "defaultValue": "0.0.1",
+ "displayName": "Mod Version"
+ },
+ "ModAuthor": {
+ "type": "parameter",
+ "description": "The name of who is developing the mod.",
+ "datatype": "text",
+ "replaces": "{ModAuthor}",
+ "displayName": "Author",
+ "defaultValue": ""
+ },
+ "ModDescription": {
+ "type": "parameter",
+ "description": "A short sentence describing the mod's features.",
+ "datatype": "text",
+ "replaces": "{ModDescription}",
+ "displayName": "Description",
+ "defaultValue": ""
+ },
+ "GameVersion": {
+ "type": "parameter",
+ "description": "Version of the game you are developing for.",
+ "datatype": "text",
+ "replaces": "{GameVersion}",
+ "displayName": "Game Version",
+ "defaultValue": "1.40.0"
+ },
+ "Nullable": {
+ "type": "parameter",
+ "description": "Use nullable reference types. (Recommended)",
+ "datatype": "bool",
+ "replaces": "{Nullable}",
+ "defaultValue": "true"
+ },
+ "EnableHints": {
+ "type": "parameter",
+ "description": "Includes code comments that provide helpful information.",
+ "datatype": "bool",
+ "displayName": "Enable Hints",
+ "defaultValue": "true"
+ }
+ },
+ "primaryOutputs": [
+ {"path": "Plugin.cs" }
+ ],
+ "postActions": [
+ {
+ "condition": "(HostIdentifier != \"dotnetcli\")",
+ "description": "Opens Plugin.cs in the editor",
+ "manualInstructions": [ ],
+ "actionId": "84C0DA21-51C8-4541-9940-6CA19AF04EE6",
+ "args": {
+ "files": "0"
+ },
+ "continueOnError": true
+ }
+ ]
+}
\ No newline at end of file
diff --git a/projectTemplates/BSIPA Plugin (Zenject-UI)/Directory.Build.props b/projectTemplates/BSIPA Plugin (Zenject-UI)/Directory.Build.props
new file mode 100644
index 0000000..79cb2f3
--- /dev/null
+++ b/projectTemplates/BSIPA Plugin (Zenject-UI)/Directory.Build.props
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+ ZenjectMenuPlugin
+ ZenjectMenuPlugin
+ {ModAuthor}
+ {ModVersion}
+ {GameVersion}
+ {ModDescription}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ BSIPA
+ true
+
+
+
+ true
+
+
+
\ No newline at end of file
diff --git a/projectTemplates/BSIPA Plugin (Zenject-UI)/ExampleController.cs b/projectTemplates/BSIPA Plugin (Zenject-UI)/ExampleController.cs
new file mode 100644
index 0000000..35459ac
--- /dev/null
+++ b/projectTemplates/BSIPA Plugin (Zenject-UI)/ExampleController.cs
@@ -0,0 +1,58 @@
+using System;
+using UnityEngine;
+using Zenject;
+
+namespace ZenjectMenuPlugin;
+
+internal class ExampleController : IInitializable, IDisposable
+{
+ private readonly ColorSchemesSettings colorSchemesSettings;
+
+#if (EnableHints)
+ // Zenject will inject the ColorSchemeSettings instance on creation automatically
+#endif
+ public ExampleController(ColorSchemesSettings colorSchemesSettings)
+ {
+ this.colorSchemesSettings = colorSchemesSettings;
+ }
+#if (EnableHints)
+ ///
+ /// Zenject calls IInitializable.Initialize on the first frame the object is created a single time
+ ///
+#endif
+ public void Initialize()
+ {
+ Plugin.Log.Info($"{nameof(ExampleController)} initialized");
+
+ var selectedColorScheme = colorSchemesSettings.GetSelectedColorScheme();
+#if (EnableHints)
+
+ // Logs info about the player's current color scheme
+#endif
+ Plugin.Log.Info(FormatColorScheme(selectedColorScheme));
+ }
+#if (EnableHints)
+ ///
+ /// Zenject calls IDisposable.Dispose when, in this case, the application unloads
+ ///
+#endif
+ public void Dispose()
+ {
+ Plugin.Log.Debug($"{nameof(ExampleController)} disposed");
+ }
+
+ private static string FormatColorScheme(ColorScheme colorScheme) =>
+ "Displaying the currently selected color scheme:\n" +
+ "--------------|-------------------\n" +
+ $"Left Saber: {ToRGBString(colorScheme.saberAColor)}\n" +
+ $"Right Saber: {ToRGBString(colorScheme.saberBColor)}\n" +
+ $"Walls Color: {ToRGBString(colorScheme.obstaclesColor)}\n" +
+ $"Env Color A: {ToRGBString(colorScheme.environmentColor0)}\n" +
+ $"Env Color B: {ToRGBString(colorScheme.environmentColor1)}\n" +
+ $"Env Color W: {ToRGBString(colorScheme.environmentColorW)}\n" +
+ $"Boost Color A: {ToRGBString(colorScheme.environmentColor0Boost)}\n" +
+ $"Boost Color B: {ToRGBString(colorScheme.environmentColor1Boost)}\n" +
+ $"Boost Color W: {ToRGBString(colorScheme.environmentColorWBoost)}";
+
+ private static string ToRGBString(Color color) => $"{color.r:F3}, {color.g:F3}, {color.b:F3}";
+}
\ No newline at end of file
diff --git a/projectTemplates/BSIPA Plugin (Zenject-UI)/Installers/AppInstaller.cs b/projectTemplates/BSIPA Plugin (Zenject-UI)/Installers/AppInstaller.cs
new file mode 100644
index 0000000..5485e8d
--- /dev/null
+++ b/projectTemplates/BSIPA Plugin (Zenject-UI)/Installers/AppInstaller.cs
@@ -0,0 +1,39 @@
+using Zenject;
+
+namespace ZenjectMenuPlugin.Installers;
+#if (EnableHints)
+
+// An installer is where related bindings are grouped together. A binding sets up an object for injection.
+// Zenject will handle object creation and figure out what needs to be injected automatically.
+// It's recommended to check the Zenject documentation to learn more about dependency injection and why it exists.
+// https://github.com/Mathijs-Bakker/Extenject?tab=readme-ov-file#what-is-dependency-injection
+
+// This particular installer relates to bindings that are used during Beat Saber's initialization, and are made
+// available in any context, whether that be in the menu, or during a map.
+// It is related to the PCAppInit installer in the base game.
+
+#endif
+internal class AppInstaller : Installer
+{
+ private readonly PluginConfig pluginConfig;
+
+ public AppInstaller(PluginConfig pluginConfig)
+ {
+ this.pluginConfig = pluginConfig;
+ }
+
+ public override void InstallBindings()
+ {
+#if (EnableHints)
+ // This allows the same instance of PluginConfig to be injected into in any class anywhere in the plugin
+#endif
+ Container.BindInstance(pluginConfig).AsSingle();
+#if (EnableHints)
+
+ // This will create a single instance of the type ExampleController and implement its interfaces
+ // The BindInterfacesTo shortcut is useful since you don't want to write out and remember every base type:
+ // Container.Bind(typeof(IInitializable, typeof(IDisposable)).To().AsSingle();
+#endif
+ Container.BindInterfacesTo().AsSingle();
+ }
+}
\ No newline at end of file
diff --git a/projectTemplates/BSIPA Plugin (Zenject-UI)/Installers/MenuInstaller.cs b/projectTemplates/BSIPA Plugin (Zenject-UI)/Installers/MenuInstaller.cs
new file mode 100644
index 0000000..d3d9fda
--- /dev/null
+++ b/projectTemplates/BSIPA Plugin (Zenject-UI)/Installers/MenuInstaller.cs
@@ -0,0 +1,29 @@
+using Zenject;
+using ZenjectMenuPlugin.Menu;
+
+namespace ZenjectMenuPlugin.Installers;
+#if (EnableHints)
+
+// This particular installer relates to bindings that are used in the main menu. It is related to the
+// MainSettingsMenuViewControllersInstaller installer in the base game, and its InstallBindings is called when the
+// game first loads into the main menu, and after settings are applied, which causes an internal reload of the game.
+
+#endif
+internal class MenuInstaller : Installer
+{
+ public override void InstallBindings()
+ {
+#if (EnableHints)
+ // This will create a single instance of the type SettingsMenuManager and implement its interfaces
+ // The BindInterfacesTo shortcut is useful since you don't want to write out and remember every base type:
+ // Container.Bind(typeof(IInitializable, typeof(IDisposable)).To().AsSingle();
+ // Is the same as:
+#endif
+ Container.BindInterfacesTo().AsSingle();
+#if (EnableHints)
+
+ // This will create a single instance of ExampleSettingsMenu, and lets it be injected into other types
+#endif
+ Container.Bind().AsSingle();
+ }
+}
\ No newline at end of file
diff --git a/projectTemplates/BSIPA Plugin (Zenject-UI)/Menu/ExampleSettingsMenu.cs b/projectTemplates/BSIPA Plugin (Zenject-UI)/Menu/ExampleSettingsMenu.cs
new file mode 100644
index 0000000..30b9eb6
--- /dev/null
+++ b/projectTemplates/BSIPA Plugin (Zenject-UI)/Menu/ExampleSettingsMenu.cs
@@ -0,0 +1,40 @@
+using BeatSaberMarkupLanguage.Attributes;
+using HMUI;
+using TMPro;
+using UnityEngine;
+
+namespace ZenjectMenuPlugin.Menu;
+#if (EnableHints)
+// This class is for managing the BSML resource and interact with the UI object in game.
+// To see more about components read the BSML docs. https://monkeymanboy.github.io/BSML-Docs/
+#endif
+internal class ExampleSettingsMenu
+{
+#if (EnableHints)
+ // [UIComponent] will get a specified component from the BSML object with the matching id.
+#endif
+ [UIComponent("example-image")]
+ private readonly ImageView exampleImage = null!;
+
+ [UIComponent("example-text")]
+ private readonly TextMeshProUGUI exampleText = null!;
+#if (EnableHints)
+ // The #post-parse event is provided by BSML. This action is invoked after BSML has parsed this object and
+ // all [UIComponent] and [UIObject] members have been populated. Any initialization logic for the menu should
+ // be done in here, rather than in Unity's Awake or Start events.
+#endif
+ [UIAction("#post-parse")]
+ private void PostParse()
+ {
+ Plugin.Log.Debug($"{nameof(ExampleSettingsMenu)} parsed");
+ }
+#if (EnableHints)
+ // [UIAction] will be used by UI elements like buttons to invoke methods such as the one here.
+#endif
+ [UIAction("example-action")]
+ private void ExampleAction()
+ {
+ exampleImage.color = Color.white;
+ exampleText.text = "Hello World!";
+ }
+}
\ No newline at end of file
diff --git a/projectTemplates/BSIPA Plugin (Zenject-UI)/Menu/SettingsMenuManager.cs b/projectTemplates/BSIPA Plugin (Zenject-UI)/Menu/SettingsMenuManager.cs
new file mode 100644
index 0000000..b1ece5f
--- /dev/null
+++ b/projectTemplates/BSIPA Plugin (Zenject-UI)/Menu/SettingsMenuManager.cs
@@ -0,0 +1,41 @@
+using System;
+using BeatSaberMarkupLanguage.Settings;
+using Zenject;
+
+namespace ZenjectMenuPlugin.Menu;
+
+internal class SettingsMenuManager : IInitializable, IDisposable
+{
+ private readonly ExampleSettingsMenu exampleSettingsMenu;
+ private readonly BSMLSettings bsmlSettings;
+
+ private const string MenuName = nameof(ZenjectMenuPlugin);
+ private const string ResourcePath = nameof(ZenjectMenuPlugin) + ".Menu.example.bsml";
+#if (EnableHints)
+ // Zenject will inject our ExampleSettingsMenu instance on this object's creation.
+ // BSMLSettings is bound by BSML. SiraUtil also lets us inject services from other mods.
+#endif
+ public SettingsMenuManager(ExampleSettingsMenu exampleSettingsMenu, BSMLSettings bsmlSettings)
+ {
+ this.exampleSettingsMenu = exampleSettingsMenu;
+ this.bsmlSettings = bsmlSettings;
+ }
+#if (EnableHints)
+ // Zenject will call IInitializable.Initialize for any menu bindings when the main menu loads for the first
+ // time or when the game restarts internally, such as when settings are applied.
+#endif
+ public void Initialize()
+ {
+#if (EnableHints)
+ // Adds a custom menu in the Mod Settings section of the main menu.
+#endif
+ bsmlSettings.AddSettingsMenu(MenuName, ResourcePath, exampleSettingsMenu);
+ }
+#if (EnableHints)
+ // Zenject will call IDisposable.Dispose for any menu bindings when the menu scene unloads.
+#endif
+ public void Dispose()
+ {
+ bsmlSettings.RemoveSettingsMenu(exampleSettingsMenu);
+ }
+}
\ No newline at end of file
diff --git a/projectTemplates/BSIPA Plugin (Zenject-UI)/Menu/example.bsml b/projectTemplates/BSIPA Plugin (Zenject-UI)/Menu/example.bsml
new file mode 100644
index 0000000..20f06b3
--- /dev/null
+++ b/projectTemplates/BSIPA Plugin (Zenject-UI)/Menu/example.bsml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/projectTemplates/BSIPA Plugin (Zenject-UI)/Plugin.cs b/projectTemplates/BSIPA Plugin (Zenject-UI)/Plugin.cs
new file mode 100644
index 0000000..c1f5058
--- /dev/null
+++ b/projectTemplates/BSIPA Plugin (Zenject-UI)/Plugin.cs
@@ -0,0 +1,44 @@
+using IPA;
+using IPA.Config.Stores;
+using IPA.Loader;
+using SiraUtil.Zenject;
+using ZenjectMenuPlugin.Installers;
+using IpaLogger = IPA.Logging.Logger;
+using IpaConfig = IPA.Config.Config;
+
+namespace ZenjectMenuPlugin;
+
+[Plugin(RuntimeOptions.DynamicInit), NoEnableDisable]
+internal class Plugin
+{
+ internal static IpaLogger Log { get; private set; } = null!;
+#if (EnableHints)
+ // Methods with [Init] are called when the plugin is first loaded by IPA.
+ // All the parameters are provided by IPA and are optional.
+ // The constructor is called before any method with [Init]. Only use [Init] with one constructor.
+#endif
+ [Init]
+ public Plugin(IpaLogger ipaLogger, IpaConfig ipaConfig, Zenjector zenjector, PluginMetadata pluginMetadata)
+ {
+ Log = ipaLogger;
+ zenjector.UseLogger(Log);
+
+#if (EnableHints)
+ // Creates an instance of PluginConfig used by IPA to load and store config values
+#endif
+ var pluginConfig = ipaConfig.Generated();
+
+#if (EnableHints)
+ // Instructs SiraUtil to use this installer during Beat Saber's initialization
+ // The PluginConfig is used as a constructor parameter for AppInstaller, so pass it to zenjector.Install()
+#endif
+ zenjector.Install(Location.App, pluginConfig);
+#if (EnableHints)
+
+ // Instructs SiraUtil to use this installer when the main menu initializes
+#endif
+ zenjector.Install(Location.Menu);
+
+ Log.Info($"{pluginMetadata.Name} {pluginMetadata.HVersion} initialized.");
+ }
+}
\ No newline at end of file
diff --git a/projectTemplates/BSIPA Plugin (Zenject-UI)/PluginConfig.cs b/projectTemplates/BSIPA Plugin (Zenject-UI)/PluginConfig.cs
new file mode 100644
index 0000000..5ac8f24
--- /dev/null
+++ b/projectTemplates/BSIPA Plugin (Zenject-UI)/PluginConfig.cs
@@ -0,0 +1,40 @@
+using System.Runtime.CompilerServices;
+using IPA.Config.Stores;
+
+[assembly: InternalsVisibleTo(GeneratedStore.AssemblyVisibilityTarget)]
+namespace ZenjectMenuPlugin;
+
+internal class PluginConfig
+{
+#if (EnableHints)
+ // Members must be 'virtual' if you want BSIPA to detect a value change and save the config automatically
+ // You can assign a default value to be used when the config is first created by assigning one after '='
+ // examples:
+#endif
+ // public virtual bool FeatureEnabled { get; set; } = true;
+ // public virtual int NumValue { get; set; } = 42;
+ // public virtual Color TheColor { get; set; } = new Color(0.12f, 0.34f, 0.56f);
+
+#if (EnableHints)
+ /*
+ ///
+ /// This is called whenever BSIPA reads the config from disk (including when file changes are detected).
+ ///
+ public virtual void OnReload() { }
+
+ ///
+ /// Call this to force BSIPA to update the config file. This is also called by BSIPA if it detects the file was modified.
+ ///
+ public virtual void Changed() { }
+
+ ///
+ /// Call this to have BSIPA copy the values from into this config.
+ ///
+ public virtual void CopyFrom(PluginConfig other) { }
+ */
+#else
+ // public virtual void OnReload() { }
+ // public virtual void Changed() { }
+ // public virtual void CopyFrom(PluginConfig other) { }
+#endif
+}
\ No newline at end of file
diff --git a/projectTemplates/BSIPA Plugin (Zenject-UI)/ZenjectMenuPlugin.csproj b/projectTemplates/BSIPA Plugin (Zenject-UI)/ZenjectMenuPlugin.csproj
new file mode 100644
index 0000000..2d64c43
--- /dev/null
+++ b/projectTemplates/BSIPA Plugin (Zenject-UI)/ZenjectMenuPlugin.csproj
@@ -0,0 +1,112 @@
+
+
+
+
+
+ net472
+
+
+
+
+ latest
+
+ enable
+
+ disable
+
+ true
+ true
+ $(BeatSaberDir)\Beat Saber_Data\Managed
+ false
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(BeatSaberDir)\Beat Saber_Data\Managed\BeatSaber.ViewSystem.dll
+ false
+
+
+ $(BeatSaberDir)\Plugins\BSML.dll
+ false
+
+
+ $(BeatSaberDir)\Beat Saber_Data\Managed\Colors.dll
+ false
+
+
+ $(BeatSaberDir)\Beat Saber_Data\Managed\DataModels.dll
+ false
+
+
+ $(BeatSaberDir)\Libs\Hive.Versioning.dll
+ false
+
+
+ $(BeatSaberDir)\Beat Saber_Data\Managed\IPA.Loader.dll
+ false
+
+
+ $(BeatSaberDir)\Beat Saber_Data\Managed\Main.dll
+ false
+
+
+
+
+ $(BeatSaberDir)\Plugins\SiraUtil.dll
+ false
+
+
+
+ $(BeatSaberDir)\Beat Saber_Data\Managed\System.Core.dll
+ false
+
+
+ $(BeatSaberDir)\Beat Saber_Data\Managed\Unity.TextMeshPro.dll
+ false
+
+
+ $(BeatSaberDir)\Beat Saber_Data\Managed\UnityEngine.dll
+ false
+
+
+ $(BeatSaberDir)\Beat Saber_Data\Managed\UnityEngine.CoreModule.dll
+ false
+
+
+ $(BeatSaberDir)\Beat Saber_Data\Managed\UnityEngine.UI.dll
+ False
+
+
+ $(BeatSaberDir)\Beat Saber_Data\Managed\UnityEngine.UIElementsModule.dll
+ False
+
+
+ $(BeatSaberDir)\Beat Saber_Data\Managed\UnityEngine.UIModule.dll
+ False
+
+
+ $(BeatSaberDir)\Beat Saber_Data\Managed\Zenject.dll
+ false
+
+
+ $(BeatSaberDir)\Beat Saber_Data\Managed\Zenject-usage.dll
+ false
+
+
+
+
\ No newline at end of file