New plan for developing plugins on Linux
This commit is contained in:
parent
216cd9564b
commit
fee3f72d10
19
docs/notes.md
Normal file
19
docs/notes.md
Normal file
@ -0,0 +1,19 @@
|
||||
# Notes
|
||||
|
||||
Gamedir
|
||||
|
||||
```sh
|
||||
cd ~/.local/share/BSManager/BSInstances/1.40.8
|
||||
```
|
||||
|
||||
## Logs
|
||||
|
||||
```sh
|
||||
tail -f Logs/_latest.log
|
||||
```
|
||||
|
||||
## FPFC Mode
|
||||
|
||||
Press `g` to release the mouse input from the game
|
||||
|
||||
Mouse input is broken because Wayland is not yet supported.
|
||||
419
docs/pc-modding.md
Normal file
419
docs/pc-modding.md
Normal file
@ -0,0 +1,419 @@
|
||||
# Beat Saber Plugin Development on Linux with Cursor
|
||||
|
||||
This guide is a 2026 take on the BSMG "PC Mod Development Intro" wiki, adapted for:
|
||||
|
||||
- Cursor IDE (instead of Visual Studio or Rider)
|
||||
- Linux (instead of Windows)
|
||||
- LLM-assisted development
|
||||
|
||||
The official wiki ([`vs-setup.md`](../../../src/bsmg/wiki/wiki/modding/pc/vs-setup.md),
|
||||
[`setup.md`](../../../src/bsmg/wiki/wiki/modding/pc/setup.md)) assumes a Visual Studio or
|
||||
Rider extension (BSMT) does most of the project plumbing for you. None of those
|
||||
extensions exist for Cursor / VSCode, so we drive the same toolchain by hand
|
||||
from the `dotnet` CLI. The good news: BSMT's heavy lifting actually lives in an
|
||||
MSBuild-time NuGet package (`BeatSaberModdingTools.Tasks`), so once a project
|
||||
is bootstrapped, the IDE is just a code editor.
|
||||
|
||||
## TL;DR
|
||||
|
||||
A Beat Saber plugin is a .NET Framework 4.7.2 class library that BSIPA loads at
|
||||
runtime. The compiled `.dll` is platform-agnostic CIL bytecode, so **you can
|
||||
build it on Linux and Beat Saber (running through Proton) will load it
|
||||
unmodified**. The workflow is:
|
||||
|
||||
1. Install Beat Saber + BSIPA via BSManager (Linux-friendly).
|
||||
2. Install the .NET SDK and (optionally) Mono on the host.
|
||||
3. Copy one of the BSMT project templates from
|
||||
[`UnityModdingTools.Templates.BeatSaber`](../../../src/Zingabopp/UnityModdingTools.Templates.BeatSaber)
|
||||
into a new repo and substitute the `$placeholders$`.
|
||||
4. Edit `csproj.user` to point `BeatSaberDir` at your install.
|
||||
5. `dotnet build` — the `BeatSaberModdingTools.Tasks` MSBuild package generates
|
||||
the embedded `manifest.json`, copies the DLL into `Beat Saber/Plugins/`, and
|
||||
(on `Release`) zips it for distribution.
|
||||
6. Launch Beat Saber from BSManager (or Steam with `--verbose`) and watch the
|
||||
BSIPA console.
|
||||
|
||||
The rest of this doc walks each step in detail.
|
||||
|
||||
## 1. Toolchain landscape
|
||||
|
||||
| Concern | Windows / VS-Rider workflow | Linux / Cursor workflow |
|
||||
| -------------------------- | -------------------------------------- | -------------------------------------------------------------------- |
|
||||
| Project templates | BSMT VSIX or BSMT-Rider plugin | Copy the template files manually from the BSMT template repo |
|
||||
| `manifest.json` generation | `BeatSaberModdingTools.Tasks` (MSBuild) | Same — pure NuGet, IDE-independent |
|
||||
| Reference resolution | BSMT "Beat Saber Reference Manager" UI | Hand-edit `<Reference Include="…"><HintPath>` entries in `.csproj` |
|
||||
| Build | IDE "Build" button (msbuild) | `dotnet build` (or `msbuild` from Mono) |
|
||||
| Deploy to game | BSMT post-build copy step | Same — driven by `BeatSaberModdingTools.Tasks` |
|
||||
| Run / debug | VS / Rider attach to `Beat Saber.exe` | Inspect BSIPA console + log files; remote-debug via Mono is possible |
|
||||
|
||||
The two key insights that make Cursor-on-Linux viable:
|
||||
|
||||
1. **`BeatSaberModdingTools.Tasks` is just a NuGet package.** It hooks into
|
||||
MSBuild via `build/` targets shipped in the package, so any `dotnet build`
|
||||
gets the same manifest generation, output copy, and release zipping that
|
||||
VS / Rider do. See its references in
|
||||
[`BareProjectTemplate.csproj`](../../../src/Zingabopp/UnityModdingTools.Templates.BeatSaber/BSIPA%20Plugin%20%28Bare%29/BareProjectTemplate.csproj)
|
||||
and
|
||||
[`CoreProjectTemplate.csproj`](../../../src/Zingabopp/UnityModdingTools.Templates.BeatSaber/BSIPA%20Plugin%20%28Core%29/CoreProjectTemplate.csproj).
|
||||
2. **Plugin DLLs are CIL, not native.** Beat Saber's Unity Mono runtime loads
|
||||
any `net472`-compatible assembly. Whether the assembly was produced by
|
||||
`csc.exe` on Windows or `dotnet build` on Linux makes no difference at
|
||||
runtime.
|
||||
|
||||
## 2. Install Beat Saber + BSIPA on Linux
|
||||
|
||||
Beat Saber has no native Linux binary — it runs through Proton in your Steam
|
||||
prefix at `~/.local/share/Steam/steamapps/common/Beat Saber/`. The BSMG
|
||||
[Linux Modding Guide](https://bsmg.wiki/linux-modding.html) lists three
|
||||
options; **BSManager is what BSMG currently recommends**.
|
||||
|
||||
```bash
|
||||
# 1. Install BSManager (AppImage, .deb, or AUR — see its release page)
|
||||
# https://github.com/Zagrios/bs-manager/releases
|
||||
# Linux install notes:
|
||||
# https://github.com/Zagrios/bs-manager/wiki/Linux#installation
|
||||
|
||||
# 2. Launch Beat Saber once via Steam *before* modding it (creates the prefix).
|
||||
|
||||
# 3. In BSManager:
|
||||
# - Download a "Recommended" Beat Saber version into a *managed* copy
|
||||
# (do NOT mod the Steam copy directly — Steam updates will break mods).
|
||||
# - Open that version → Mods tab → install at minimum BSIPA.
|
||||
# - Always launch the modded version from BSManager.
|
||||
```
|
||||
|
||||
If you would rather wire up BSIPA by hand (e.g. for a CI machine), the manual
|
||||
recipe is:
|
||||
|
||||
1. Add `WINEDLLOVERRIDES="winhttp=native,builtin" %command%` to Beat Saber's
|
||||
Steam launch options.
|
||||
2. Drop `BSIPA-x64-Net4.zip` into the game folder, then run
|
||||
`wine IPA.exe -n` from inside it.
|
||||
3. Verify a `Plugins/` folder is created next to `Beat Saber.exe`.
|
||||
|
||||
The full BSIPA install reference is at
|
||||
<https://nike4613.github.io/BeatSaber-IPA-Reloaded/articles/start-user.html>.
|
||||
|
||||
::: tip Pin a known game version
|
||||
|
||||
Steam will silently update Beat Saber and break your mod. Either let BSManager
|
||||
hold a pinned download (preferred) or set the Steam app to "Only update this
|
||||
game when I launch it" and skip launching from Steam.
|
||||
|
||||
:::
|
||||
|
||||
## 3. Host toolchain
|
||||
|
||||
Install once on the host:
|
||||
|
||||
```bash
|
||||
# Pick whichever your distro provides (examples for the most common ones)
|
||||
sudo pacman -S dotnet-sdk # Arch
|
||||
sudo apt install dotnet-sdk-9.0 # Debian/Ubuntu
|
||||
sudo dnf install dotnet-sdk-9.0 # Fedora
|
||||
```
|
||||
|
||||
Verify:
|
||||
|
||||
```bash
|
||||
dotnet --list-sdks # any 6.0+ SDK can build net472 targets
|
||||
```
|
||||
|
||||
You do **not** need Mono for building. The `dotnet` SDK plus the NuGet
|
||||
`Microsoft.NETFramework.ReferenceAssemblies` package (pulled in transitively
|
||||
by `BeatSaberModdingTools.Tasks`) is sufficient to produce `net472` assemblies
|
||||
on Linux. Install Mono only if you want to run / debug `.NET Framework` test
|
||||
harnesses outside the game.
|
||||
|
||||
Optional but recommended:
|
||||
|
||||
- `nuget` CLI (for inspecting / restoring packages outside `dotnet`).
|
||||
- `ilspycmd` or `ILSpy` for reading decompiled game code.
|
||||
|
||||
## 4. Cursor extensions for C\#
|
||||
|
||||
Cursor's marketplace doesn't carry Microsoft's official `C#` /
|
||||
`C# Dev Kit` extensions (their license restricts them to VS Code / VS).
|
||||
Workable replacements that ship through Open VSX / sideloads:
|
||||
|
||||
| Need | Extension |
|
||||
| ----------------------------- | -------------------------------------------------------- |
|
||||
| Language server (LSP) | `muhammad-sammy.csharp` (community fork of OmniSharp) |
|
||||
| or | `Ionide.csharp` / `csharp-language-server` if preferred |
|
||||
| Debugger | `vsdbg` is MS-licensed; on Linux use `netcoredbg` via |
|
||||
| | `muhammad-sammy.csharp`'s built-in debugger |
|
||||
| `.csproj` / MSBuild awareness | Comes with the language-server extension above |
|
||||
| XAML / `.bsml` | Plain XML support is enough; no dedicated BSML extension |
|
||||
|
||||
Install from Cursor: `Ctrl+Shift+X` → search the names above. If a package is
|
||||
not in the marketplace, grab the `.vsix` from
|
||||
<https://open-vsx.org/> and use **Install from VSIX…**.
|
||||
|
||||
Settings worth tweaking in `settings.json`:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
// Force OmniSharp/Roslyn to load the right SDK
|
||||
"dotnet.server.useOmnisharp": true,
|
||||
// Prevent the language server from chewing on the Beat Saber game DLLs
|
||||
"files.watcherExclude": {
|
||||
"**/Refs/**": true,
|
||||
"**/bin/**": true,
|
||||
"**/obj/**": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 5. Bootstrap a new plugin project
|
||||
|
||||
The BSMT templates are designed to be expanded by Visual Studio's templating
|
||||
engine — they contain `$safeprojectname$`, `$guid1$`, and
|
||||
`$targetframeworkversion$` placeholders. We expand them by hand. Pick the
|
||||
template that matches what you want:
|
||||
|
||||
| Template | When to use |
|
||||
| ----------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- |
|
||||
| [`BSIPA Plugin (Bare)`](../../../src/Zingabopp/UnityModdingTools.Templates.BeatSaber/BSIPA%20Plugin%20%28Bare%29) | Smallest possible BSIPA plugin — `Plugin.cs` + `manifest.json`. |
|
||||
| [`BSIPA Plugin (Core)`](../../../src/Zingabopp/UnityModdingTools.Templates.BeatSaber/BSIPA%20Plugin%20%28Core%29) | Adds a `MonoBehaviour` controller and a commented config example. |
|
||||
| [`BSIPA Plugin (Disableable)`](../../../src/Zingabopp/UnityModdingTools.Templates.BeatSaber/BSIPA%20Plugin%20%28Disableable%29) | Plugin that can be enabled/disabled at runtime. |
|
||||
|
||||
The walkthrough below uses **Core** and a fictional plugin called `MyPlugin`.
|
||||
|
||||
### 5.1 Copy the template
|
||||
|
||||
```bash
|
||||
SRC="$HOME/src/Zingabopp/UnityModdingTools.Templates.BeatSaber/BSIPA Plugin (Core)"
|
||||
mkdir -p ~/src/yourname/MyPlugin && cd ~/src/yourname/MyPlugin
|
||||
|
||||
cp "$SRC"/Plugin.cs Plugin.cs
|
||||
cp "$SRC"/MonobehaviourTemplate.cs MyPluginController.cs
|
||||
cp "$SRC"/PluginConfig.cs Configuration/PluginConfig.cs
|
||||
mkdir -p Properties
|
||||
cp "$SRC"/AssemblyInfo.cs Properties/AssemblyInfo.cs
|
||||
cp "$SRC"/manifest.json manifest.json
|
||||
cp "$SRC"/CoreProjectTemplate.csproj MyPlugin.csproj
|
||||
cp "$SRC"/csproj.user.template MyPlugin.csproj.user
|
||||
cp "$SRC"/Directory.Build.props.template Directory.Build.props
|
||||
```
|
||||
|
||||
### 5.2 Substitute placeholders
|
||||
|
||||
The VS template engine would normally do this. Replace these tokens across
|
||||
every file:
|
||||
|
||||
| Token | Replace with |
|
||||
| ------------------------------ | ------------------------------------------------------------------------- |
|
||||
| `$safeprojectname$` | `MyPlugin` |
|
||||
| `$projectname$` | `My Plugin` (display name; can equal the safe name) |
|
||||
| `$guid1$` | A fresh GUID — `uuidgen` then wrap as `{XXXXXXXX-…}` |
|
||||
| `$targetframeworkversion$` | `4.7.2` |
|
||||
| Any reference to `$safeprojectname$Controller` | `MyPluginController` (in `Plugin.cs` + the controller filename) |
|
||||
|
||||
A one-shot rewrite:
|
||||
|
||||
```bash
|
||||
GUID="{$(uuidgen | tr a-f A-F)}"
|
||||
find . -type f \( -name '*.cs' -o -name '*.csproj' -o -name '*.user' -o -name 'manifest.json' \) \
|
||||
-exec sed -i \
|
||||
-e "s|\$safeprojectname\$|MyPlugin|g" \
|
||||
-e "s|\$projectname\$|My Plugin|g" \
|
||||
-e "s|\$guid1\$|$GUID|g" \
|
||||
-e "s|\$targetframeworkversion\$|4.7.2|g" {} +
|
||||
```
|
||||
|
||||
### 5.3 Tell MSBuild where Beat Saber lives
|
||||
|
||||
Edit `MyPlugin.csproj.user` (this file should be `.gitignore`'d — paths are
|
||||
machine-specific):
|
||||
|
||||
```xml
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<BeatSaberDir>/home/you/.local/share/Steam/steamapps/common/Beat Saber</BeatSaberDir>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
```
|
||||
|
||||
If you mod a BSManager-managed copy instead of the Steam copy, point at that
|
||||
folder (typically under `~/BSManager/versions/<version>/`). All the
|
||||
`<HintPath>$(BeatSaberDir)\Beat Saber_Data\Managed\…</HintPath>` entries in
|
||||
`MyPlugin.csproj` resolve through that variable. Backslashes work fine — MSBuild
|
||||
normalises them on Linux.
|
||||
|
||||
### 5.4 Fill in your manifest
|
||||
|
||||
Open `manifest.json` and set `id`, `name`, `author`, `version`, `description`,
|
||||
and (importantly) `gameVersion` — the value here is what BSIPA shows the user
|
||||
when your plugin is loaded against a different game version.
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/bsmg/BSIPA-MetadataFileSchema/master/Schema.json",
|
||||
"id": "MyPlugin",
|
||||
"name": "My Plugin",
|
||||
"author": "you",
|
||||
"version": "0.1.0",
|
||||
"description": "What this plugin does in one or two sentences.",
|
||||
"gameVersion": "1.42.3",
|
||||
"dependsOn": {
|
||||
"BSIPA": "^4.3.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`gameVersion` should match the major.minor.patch of the game you are targeting
|
||||
(check `BeatSaberVersion.txt` in the install dir — yours is `1.42.3_15380`,
|
||||
i.e. `1.42.3`). Add other plugins (e.g. `BeatSaberMarkupLanguage`,
|
||||
`SiraUtil`) to `dependsOn` as needed.
|
||||
|
||||
### 5.5 Initial build
|
||||
|
||||
```bash
|
||||
cd ~/src/yourname/MyPlugin
|
||||
dotnet restore
|
||||
dotnet build -c Debug
|
||||
```
|
||||
|
||||
The first restore pulls down `BeatSaberModdingTools.Tasks` and the .NET
|
||||
Framework reference assemblies. After the build succeeds you should see:
|
||||
|
||||
- `bin/Debug/MyPlugin.dll` (and `MyPlugin.pdb`).
|
||||
- A copy of the same DLL inside `<BeatSaberDir>/Plugins/`. This is done by
|
||||
the BSMT MSBuild target `CopyToPlugins`. Disable it on CI by passing
|
||||
`-p:DisableCopyToPlugins=True`.
|
||||
|
||||
If the build fails complaining about missing `Main.dll`, `HMUI.dll`, etc.,
|
||||
your `BeatSaberDir` is wrong or pointing at an unmodded game (the Managed
|
||||
folder must contain those DLLs).
|
||||
|
||||
### 5.6 Release builds
|
||||
|
||||
```bash
|
||||
dotnet build -c Release
|
||||
```
|
||||
|
||||
This produces `bin/Release/MyPlugin.dll` plus a distributable
|
||||
`bin/Release/zip/MyPlugin-<version>.zip` shaped to drop into the game folder.
|
||||
|
||||
## 6. Iteration loop
|
||||
|
||||
1. Edit C# in Cursor; the OmniSharp-style language server gives you completion
|
||||
against the game's own DLLs (it follows the `<HintPath>` entries).
|
||||
2. `dotnet build` — the DLL lands in `<BeatSaberDir>/Plugins/` automatically.
|
||||
3. Launch Beat Saber from BSManager with the `--verbose --debug` arguments
|
||||
set under "Advanced launch", or from Steam with the same flags appended to
|
||||
the launch options. BSManager already exposes a "Debug mode" toggle that
|
||||
adds `--verbose`.
|
||||
4. Watch the BSIPA console window or `Logs/_latest.log` in the game folder.
|
||||
|
||||
Useful launch arguments (full list in the BSMG
|
||||
[index page](../../../src/bsmg/wiki/wiki/modding/pc/index.md)):
|
||||
|
||||
| Flag | Effect |
|
||||
| -------------- | ------------------------------------------------------- |
|
||||
| `--verbose` | Open the BSIPA console window. |
|
||||
| `--debug` | Promote `Debug.Log(…)` calls to console output. |
|
||||
| `--trace` | Even noisier — BSIPA-internal traces. |
|
||||
| `fpfc` | First-Person Flying Controller — play without VR. |
|
||||
| `--auto_play` | Built-in autoplayer (handy for testing UI/menu mods). |
|
||||
|
||||
For a tighter loop, point your Steam compatibility tool at GE-Proton (newer
|
||||
than the Valve build) and add `PROTON_LOG=1` so Wine logs land in
|
||||
`~/steam-MyPlugin.log`.
|
||||
|
||||
## 7. Debugging
|
||||
|
||||
True breakpoint debugging requires attaching Mono Soft Debugger to the
|
||||
Unity Mono runtime that ships with Beat Saber. The procedure:
|
||||
|
||||
1. Add `--mono-debugger` to Beat Saber's launch arguments. Unity's Mono will
|
||||
open a debugger socket on `127.0.0.1:55555` by default.
|
||||
2. In Cursor, install **MonoDebug** (`MetinSeylan.mono-debug`) or use
|
||||
`dnSpyEx`'s Mono debugger from a separate window.
|
||||
3. The plugin must be built with `<DebugType>portable</DebugType>` (the
|
||||
templates already do this for Debug).
|
||||
|
||||
In practice most mod authors lean on `Plugin.Log.Info(…)` + the BSIPA console
|
||||
because it survives Proton's quirks better than the Mono debugger.
|
||||
|
||||
For inspecting the game's own assemblies, use [ILSpy](https://github.com/icsharpcode/ILSpy)
|
||||
or the CLI:
|
||||
|
||||
```bash
|
||||
dotnet tool install -g ilspycmd
|
||||
ilspycmd "$HOME/.local/share/Steam/steamapps/common/Beat Saber/Beat Saber_Data/Managed/Main.dll" \
|
||||
-o ~/decompiled/
|
||||
```
|
||||
|
||||
The BSMG wiki has a dedicated [decompiling guide](../../../src/bsmg/wiki/wiki/modding/pc/decompiling.md).
|
||||
|
||||
## 8. Tips for LLM-assisted development
|
||||
|
||||
A few things make this codebase friendlier than average to LLM agents:
|
||||
|
||||
- **The reference graph is closed.** All Beat Saber types live under
|
||||
`Beat Saber_Data/Managed/`. Have your agent run
|
||||
`ilspycmd …/Managed/Main.dll -o decompiled/` once and grep the result when
|
||||
it needs to know a method signature. Cache it in the repo (gitignored).
|
||||
- **`manifest.json` is the source of truth for runtime dependencies**. When
|
||||
your agent adds a `using BeatSaberMarkupLanguage…`, it must also add
|
||||
`"BeatSaberMarkupLanguage": "^1.x"` to `dependsOn` and a corresponding
|
||||
`<Reference>` in the `.csproj` — otherwise BSIPA will refuse to load the
|
||||
plugin or the build will fail to find the type.
|
||||
- **No nullable reference types in templates.** The BSMT templates are
|
||||
pre-`<Nullable>enable</Nullable>`. Either keep that style or flip the
|
||||
switch in `MyPlugin.csproj` and let the agent maintain `?`/`!` annotations
|
||||
consistently.
|
||||
- **Harmony patches are runtime-reflective.** Static analysis can't catch a
|
||||
typo in a `[HarmonyPatch(typeof(Foo), nameof(Foo.Bar))]` attribute — add a
|
||||
smoke test that asserts the patch attached at startup (BSIPA logs an error
|
||||
if a patch fails to apply, so a log-line check works).
|
||||
- **Game updates change DLL ABIs.** Pin a `gameVersion` and verify it on
|
||||
startup; tell the agent to bail out loudly rather than silently wrap an
|
||||
exception when the API drift is too large.
|
||||
|
||||
## 9. Repo layout suggestion
|
||||
|
||||
```
|
||||
MyPlugin/
|
||||
├─ .gitignore # ignore bin/, obj/, *.csproj.user, decompiled/
|
||||
├─ Directory.Build.props # BSMT switches (ImportBSMTTargets, BSMTProjectType)
|
||||
├─ MyPlugin.csproj # references + BeatSaberModdingTools.Tasks
|
||||
├─ MyPlugin.csproj.user # local BeatSaberDir — gitignored
|
||||
├─ manifest.json # BSIPA metadata (embedded into DLL at build time)
|
||||
├─ Plugin.cs # BSIPA entry point
|
||||
├─ MyPluginController.cs # MonoBehaviour singleton
|
||||
├─ Configuration/
|
||||
│ └─ PluginConfig.cs # BSIPA Generated config (uncomment to enable)
|
||||
├─ Properties/
|
||||
│ └─ AssemblyInfo.cs
|
||||
└─ Refs/ # optional fallback for Beat Saber DLLs
|
||||
# (LocalRefsDir wins over BeatSaberDir if present)
|
||||
```
|
||||
|
||||
A starter `.gitignore`:
|
||||
|
||||
```gitignore
|
||||
bin/
|
||||
obj/
|
||||
*.csproj.user
|
||||
decompiled/
|
||||
.vs/
|
||||
.idea/
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
- BSMG wiki — Linux modding: <https://bsmg.wiki/linux-modding.html>
|
||||
- BSMG wiki — PC mod dev intro: [`setup.md`](../../../src/bsmg/wiki/wiki/modding/pc/setup.md)
|
||||
- BSMG wiki — VS variant of the setup: [`vs-setup.md`](../../../src/bsmg/wiki/wiki/modding/pc/vs-setup.md)
|
||||
- BSMG wiki — launch flags etc.: [`index.md`](../../../src/bsmg/wiki/wiki/modding/pc/index.md)
|
||||
- BSIPA install reference: <https://nike4613.github.io/BeatSaber-IPA-Reloaded/articles/start-user.html>
|
||||
- `BeatSaberModdingTools.Tasks` (the MSBuild engine that powers the templates):
|
||||
<https://www.nuget.org/packages/BeatSaberModdingTools.Tasks>
|
||||
- BSMT VS extension source (read-only reference for what the IDE plugin
|
||||
automates): [`~/src/denpadokei/BeatSaberModdingTools`](../../../src/denpadokei/BeatSaberModdingTools)
|
||||
- BSMT project templates (the ones we copy from): [`~/src/Zingabopp/UnityModdingTools.Templates.BeatSaber`](../../../src/Zingabopp/UnityModdingTools.Templates.BeatSaber)
|
||||
- BSManager (recommended Linux installer): <https://github.com/Zagrios/bs-manager>
|
||||
- BSIPA repo — Unity mod injector (reference): [`~/src/nike4613/BeatSaber-IPA-Reloaded`](../../../src/nike4613/BeatSaber-IPA-Reloaded)
|
||||
- Song Core — plugin for handling custom song additions [`~/src/Kylemc1413/SongCore`](../../../src/Kylemc1413/SongCore)
|
||||
Loading…
x
Reference in New Issue
Block a user