# Dalamud Plugin Template A starting point for FFXIV/Dalamud plugins on the [Hellion Forge](https://gitea.hellion-forge.cloud/Hellion-Forge). Built on the **official goatcorp [Dalamud Sample Plugin](https://github.com/goatcorp/SamplePlugin)** (working code with goat-image demo, MainWindow with PlayerState/Lumina queries, ConfigWindow with movable-toggle), wrapped with Hellion-Forge conventions: custom-repo manifest, Forge-Auto-Announce workflow, version-bump checklist, MIT license. The sample code is intentionally kept intact so the template builds and runs out of the box. Strip the goat demo when you implement your real plugin (see "Replacing the sample" below). --- ## How to use this template 1. Click **"Use this template"** at the top of the repository page on the Forge. 2. Pick a name like `MyPlugin` and clone your new repo locally. 3. Find-and-replace `PluginNameTemplate` everywhere with your plugin's name (case-sensitive): ```bash git ls-files | xargs sed -i 's/PluginNameTemplate/MyPlugin/g' git mv PluginNameTemplate.csproj MyPlugin.csproj git mv PluginNameTemplate.yaml MyPlugin.yaml git mv PluginNameTemplate.sln MyPlugin.sln ``` 4. Replace `images/icon.png` with your plugin icon (512x512 PNG, transparent background). 5. Update `repo.json` with your real `DownloadLinkInstall` URLs once your CI publishes releases. 6. Strip the goat demo (or keep it for development reference — your call). 7. Implement your plugin in `src/Plugin.cs` and friends. After the rename, this README should be replaced with your plugin's actual README — the template-usage notes don't belong in your shipped plugin. --- ## Replacing the sample The template ships with the goat demo working end-to-end so you can verify your build setup before writing any code. To remove it cleanly: 1. **Empty the windows.** `src/Windows/MainWindow.cs` and `src/Windows/ConfigWindow.cs` — replace the goat-image / config-toggle demos with your real UI. Keep the class structure (constructor signature, `Draw()` override). 2. **Delete the goat asset.** `Data/goat.png` and the `` block in `.csproj`. 3. **Adjust services.** `src/Plugin.cs` injects `ITextureProvider`, `IClientState`, `IPlayerState`, `IDataManager` — only because the goat demo uses them. Drop the ones you don't need. 4. **Rename `/pmycommand`.** In `src/Plugin.cs`, change `private const string CommandName = "/pmycommand"` to your plugin's actual command and update the `HelpMessage`. --- ## Project structure ``` . ├── .editorconfig Code style ├── .gitea/ │ ├── ISSUE_TEMPLATE/ Standard issue forms │ ├── PULL_REQUEST_TEMPLATE.md │ ├── forge-posts/v0.1.0.md Discord-announcement payload (Forge-Auto-Announce) │ └── workflows/ │ ├── ci.yml Build verification on push/PR │ └── forge-auto-announce.yml Discord announcement on tag ├── Data/ │ └── goat.png Sample asset for the working demo (replace or delete) ├── docs/CHANGELOG.md Long-form changelog ├── images/.gitkeep Plugin icon goes here (icon.png) ├── src/ │ ├── Plugin.cs IDalamudPlugin entry, WindowSystem, command handler │ ├── Configuration.cs IPluginConfiguration │ ├── packages.lock.json NuGet lockfile (Dalamud SDK manages this) │ └── Windows/ │ ├── ConfigWindow.cs Movable-toggle demo │ └── MainWindow.cs Goat + PlayerState/Lumina demo ├── PluginNameTemplate.csproj Dalamud-SDK 15.0.0 csproj ├── PluginNameTemplate.sln Solution file ├── PluginNameTemplate.yaml Dalamud manifest ├── repo.json Custom-repo manifest for testers ├── CHANGELOG.md Slim changelog (latest 2-4 versions) ├── CODEOWNERS Default reviewer ├── LICENSE MIT └── README.md This file (replace before shipping) ``` --- ## Build ```bash dotnet restore dotnet build -c Release ``` DalamudPackager produces the `.zip` artifact under `bin/Release//latest.zip`. **Note:** Don't override the default `DalamudPackager.targets` from your csproj — it'll silently strip the icon and ImageUrls from your manifest. If you need custom packaging, do it via csproj properties only. --- ## Versioning Synchronized version fields (bump all at once): - `.csproj` → `Version`, `AssemblyVersion`, `FileVersion` - `.yaml` → `assembly_version` + `changelog` - `repo.json` → `AssemblyVersion`, `TestingAssemblyVersion`, all 3 `DownloadLink*` URLs, `Description`, `Changelog` - `CHANGELOG.md` (slim) and `docs/CHANGELOG.md` (full) — keep the latest 2-4 versions in the slim copy - `.gitea/forge-posts/v.md` — Discord announcement payload Sanity-check before tagging: ```bash grep -rn "" . | grep -v -E '(bin|obj|node_modules|.git/)' ``` The Forge-Auto-Announce workflow reads from the **tagged tree**, not main. If a fix-commit lands after the tag, force-push the tag. --- ## Dalamud SDK version This template targets `Dalamud.NET.Sdk/15.0.0` and `dalamud_api_level: 15` in the manifest. When the SDK bumps: 1. Update `` in the csproj 2. Update `dalamud_api_level: X` in the yaml 3. Check the SDK release notes for breaking API changes 4. Run a clean build (`dotnet clean && dotnet build`) and validate the goat demo still works --- ## Testing Service classes coupled to Dalamud (`IPluginInterface`, `IDataManager`, etc.) cannot be instantiated directly in xUnit because the Dalamud assembly isn't on the test AppDomain. Patterns that work: - **Pure helpers** — extract logic into Dalamud-free classes, test those directly - **Constructor injection** — pass utility dependencies in, mock them in tests - **External test repo** — keep tests in a private side-repo if they need a richer harness The default csproj has no test project. Add one when there's something to test. --- ## License MIT — see `LICENSE`. The base sample-code is from goatcorp's Dalamud SamplePlugin (AGPL-3.0 in upstream); the working translation here is shipped under MIT alongside the Hellion-specific scaffolding. If you ship a plugin that's a near-1:1 fork of the upstream sample, check the upstream license for your distribution.