diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..524fb1b --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,30 @@ +# Automatically build the project and run any configured tests for every push +# and submitted pull request. This can help catch issues that only occur on +# certain platforms or Java versions, and provides a first line of defence +# against bad commits. + +name: build +on: [pull_request, push] + +jobs: + build: + runs-on: ubuntu-24.04 + steps: + - name: checkout repository + uses: actions/checkout@v6 + - name: validate gradle wrapper + uses: gradle/actions/wrapper-validation@v6 + - name: setup jdk + uses: actions/setup-java@v5 + with: + java-version: '25' + distribution: 'microsoft' + - name: make gradle wrapper executable + run: chmod +x ./gradlew + - name: build + run: ./gradlew build + - name: capture build artifacts + uses: actions/upload-artifact@v7 + with: + name: Artifacts + path: build/libs/ diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..08247c8 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,45 @@ +# Creates a GitHub Release whenever a version tag (v*) is pushed. +# The release body is the matching section from CHANGELOG.md and the +# built plugin jar is attached as an asset. + +name: release +on: + push: + tags: + - 'v*' + +permissions: + contents: write + +jobs: + release: + runs-on: ubuntu-24.04 + steps: + - name: checkout repository + uses: actions/checkout@v6 + - name: setup jdk + uses: actions/setup-java@v5 + with: + java-version: '25' + distribution: 'microsoft' + - name: make gradle wrapper executable + run: chmod +x ./gradlew + - name: build + run: ./gradlew build + - name: extract changelog section + run: | + VERSION="${GITHUB_REF_NAME#v}" + awk -v ver="$VERSION" ' + $0 == "## Version " ver { found = 1; next } + found && /^## / { exit } + found { print } + ' CHANGELOG.md > RELEASE_NOTES.md + if ! grep -q '[^[:space:]]' RELEASE_NOTES.md; then + echo "::error::No changelog section found for version $VERSION in CHANGELOG.md" + exit 1 + fi + - name: create release + uses: softprops/action-gh-release@v2 + with: + body_path: RELEASE_NOTES.md + files: build/libs/*.jar diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..8b9c078 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,3 @@ +# TriHunt - Change Log + +## Unreleased diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..366e5ab --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,67 @@ +# TriHunt — Agent Instructions + +TriHunt is a Manhunt plugin for Paper servers (Kotlin 2.3.10, Minecraft 26.2, Java 25): the Speedrunners race to beat +the chosen boss while the Hunters try to stop them. [README.md](README.md) has the player-facing overview. + +## After every change: keep the changelog and docs in sync + +Before finishing any task that changes the plugin, do all of the following: + +1. **Update the changelog** — add an entry for the change under `## Unreleased` in [CHANGELOG.md](CHANGELOG.md), in the + same commit as the change. Every new feature gets an entry, and so does every improvement and fix. + - Follow the SkyHanni-style format documented in [docs/RELEASING.md](docs/RELEASING.md): category (`### New + Features` / `### Improvements` / `### Fixes` / `### Technical Details` / `### Removed Features`), then a + `#### Feature Area` heading, then `+` bullets. + - Reuse the category and feature-area headings already under `## Unreleased` instead of repeating them. + - Write player- and server-owner-facing entries for gameplay changes; put refactors, build, and tooling changes + under `### Technical Details`. + - Never edit the section of a version that has already been released. + - Skip changelog entries only for changes with no effect on the shipped plugin or its workflow (e.g. fixing a typo + in a doc). + +2. **Update the developer docs** — if the change adds or alters a base class, registrar, utility, or data API, update + [docs/DEVELOPER_GUIDE.md](docs/DEVELOPER_GUIDE.md) or [docs/UTILITY_GUIDE.md](docs/UTILITY_GUIDE.md) in the same + task. A change to a documented workflow (e.g. the release process in [docs/RELEASING.md](docs/RELEASING.md)) updates + that doc too. + +3. **Check the README** — if the change affects anything [README.md](README.md) mentions (game modes, features, planned + features, getting started), update it. When a planned feature ships, move it out of **Planned Features**. + +## Build & run + +```powershell +./gradlew build # Builds build/libs/TriHunt-.jar +./gradlew copyPlugin # Copies the jar into run/plugins/ +./gradlew startServer # Runs copyPlugin, then launches the paper-*.jar in run/ +``` + +## Project conventions + +- Plugin code is Kotlin under `src/main/kotlin/net/trilleo/mc/plugins/trihunt/`; `Main.kt` is the entry point. +- **Auto-registration** — `PackageScanner` discovers concrete classes at startup, so there is no manual wiring and no + `plugin.yml` edit. Extend the right base class and place the file in the right package: + + | Component | Base Class | Package | + |:------------|:----------------|:------------------------| + | Command | `PluginCommand` | `commands` (any depth) | + | Listener | `Listener` | `listeners` (any depth) | + | GUI | `PluginGUI` | `guis` (any depth) | + | Task | `PluginTask` | `tasks` (any depth) | + | Item | `PluginItem` | `items` (any depth) | + | Recipe | `PluginRecipe` | `recipes` (any depth) | + | Config | `PluginConfig` | `config` (any depth) | + | Player data | `PlayerData` | `data` | + | Server data | `ServerData` | `data` | + + Permissions are derived from commands automatically. Every command, listener, GUI, and task needs either a no-arg + constructor or one accepting a `JavaPlugin`. See [docs/DEVELOPER_GUIDE.md](docs/DEVELOPER_GUIDE.md). +- `plugin_version` in [gradle.properties](gradle.properties) is the single source of truth for the plugin version. It + flows into the jar filename and, through `processResources`, into `plugin.yml` (`version: ${projectVersion}`) — never + hardcode a version in `plugin.yml` or `build.gradle.kts`. +- [.github/workflows/build.yml](.github/workflows/build.yml) builds every push and pull request. Releases are made by + tagging `vX.Y.Z` — see [docs/RELEASING.md](docs/RELEASING.md). **Never tag or push tags unless explicitly asked** — + pushing a tag publishes a release. +- Commit messages follow the `: ` convention (`Feature:`, `Improvement:`, `Fix:`, `Internal:`, + `Backend:`, `Update:`) with one granular commit per logical change — see + [docs/COMMIT_STRUCTURE.md](docs/COMMIT_STRUCTURE.md). A `Feature:`, `Improvement:`, or `Fix:` commit carries its own + changelog entry. diff --git a/README.md b/README.md index db2fadb..5eb136d 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,8 @@ Custom items and recipes to enhance the gameplay experience. ## 🎮 Getting Started -Install the plugin and use the hotbar item to start! +Download the latest jar from the [releases page](https://github.com/Trilleo/TriHunt/releases), install the plugin and +use the hotbar item to start! See the [change log](CHANGELOG.md) for what's new in each release. --- diff --git a/build.gradle.kts b/build.gradle.kts index a67f544..cb8987d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,7 +4,7 @@ plugins { } group = "net.trilleo" -version = "0.7.0" +version = providers.gradleProperty("plugin_version").get() idea { module { @@ -38,6 +38,14 @@ dependencies { compileOnly("io.papermc.paper:paper-api:26.2.build.+") } +tasks.processResources { + val props = mapOf("projectVersion" to version) + inputs.properties(props) + filesMatching("plugin.yml") { + expand(props) + } +} + tasks.jar { from(configurations.runtimeClasspath.get().map { zipTree(it) }) duplicatesStrategy = DuplicatesStrategy.EXCLUDE diff --git a/docs/COMMIT_STRUCTURE.md b/docs/COMMIT_STRUCTURE.md index 404e064..c9ce9d6 100644 --- a/docs/COMMIT_STRUCTURE.md +++ b/docs/COMMIT_STRUCTURE.md @@ -16,7 +16,7 @@ Every commit message must follow this syntax: | **Fix** | Repairing bugs, crashes, or logic errors. | `Fix: Resolve /help command output error` | | **Improvement** | Refining existing code, UX, or performance. | `Improvement: Add tiered role removal logic` | | **Internal** | Documentation, comments, or repository maintenance. | `Internal: Update COMMIT_STRUCTURE instructions` | -| **Backend** | Database schema changes or configuration updates. | `Backend: Add FeatureSwitch model for toggles` | +| **Backend** | Build system, dependency, or configuration updates. | `Backend: Update Gradle to 9.7.1` | | **Update** | Plugin version changes. | `Update: 1.0.0 release` | ## Best Practices @@ -25,4 +25,17 @@ Every commit message must follow this syntax: * **Be Specific:** Instead of `Fix: bug`, use `Fix: Handle undefined member in /role command`. * **No Period at End:** Do not end the commit message with a period. ---- \ No newline at end of file +## Mapping to Changelog Categories + +Tags roughly correspond to [CHANGELOG.md](../CHANGELOG.md) categories (see [RELEASING.md](RELEASING.md) for the +changelog format): + +| Tag | Changelog category | +|:---------------------------|:------------------------| +| **Feature** | `### New Features` | +| **Improvement** | `### Improvements` | +| **Fix** | `### Fixes` | +| **Backend** / **Internal** | `### Technical Details` | +| **Update** | Usually no entry | + +--- diff --git a/docs/RELEASING.md b/docs/RELEASING.md new file mode 100644 index 0000000..9c7df99 --- /dev/null +++ b/docs/RELEASING.md @@ -0,0 +1,127 @@ +# TriHunt - Changelog & Releasing + +This guide covers how to maintain [CHANGELOG.md](../CHANGELOG.md) during development and how to publish a release on +GitHub. The release itself is automated by [.github/workflows/release.yml](../.github/workflows/release.yml) — pushing +a version tag builds the plugin, extracts the matching changelog section, and creates the GitHub Release with the jar +attached. Every push and pull request is also built by [.github/workflows/build.yml](../.github/workflows/build.yml). + +## Changelog format + +The changelog follows the [SkyHanni](https://github.com/hannibal002/SkyHanni) style: + +```markdown +# TriHunt - Change Log + +## Unreleased + +## Version 1.1.0 + +### New Features + +#### Game Modes + ++ Added the Armed special mode. + + Speedrunners start with a full set of iron gear. + +### Improvements + +#### Compass + ++ Made the tracking compass point to the last portal used when the Speedrunner is in another dimension. + +### Fixes + +#### Items + ++ Fixed custom recipes not showing in the recipe book. +``` + +Structure, top to bottom: + +| Level | Heading | Purpose | +|--------|--------------------------------|---------------------------------------------------------------------------------------| +| `##` | `Unreleased` / `Version X.Y.Z` | One section per release; `Unreleased` collects entries during development | +| `###` | Category | `New Features`, `Improvements`, `Fixes`, `Technical Details`, `Removed Features` | +| `####` | Feature area | `Game Modes`, `Compass`, `Items`, `Misc`, … — free-form, `Misc` is the catch-all | +| `+` | Entry | One change per bullet; indent `+` sub-bullets for details | + +Rules of thumb: + +- Add an entry under `## Unreleased` in the same commit (or PR) as the change itself, so the changelog never lags + behind. +- Only include categories and feature areas that actually have entries — omit empty ones. +- Write entries for players and server owners, not developers: "Added the Armed special mode", not + "Refactored the game timer". Developer-facing changes go under `Technical Details`. +- With outside contributors, append attribution like SkyHanni does: + `+ Added X. - Name (https://github.com/Trilleo/TriHunt/pull/123)` + +## Versioning + +`plugin_version` in [gradle.properties](../gradle.properties) is the single source of truth — it flows into the jar +filename and the `version` field of `plugin.yml` automatically. Follow semver: **patch** for bugfixes, **minor** for new +features, **major** for breaking changes (e.g. config or data resets). + +## Release walkthrough + +Example: releasing version `1.1.0`. + +1. **Finalize the changelog** — in `CHANGELOG.md`, rename the `## Unreleased` heading to `## Version 1.1.0` and add a + fresh empty `## Unreleased` above it: + + ```markdown + ## Unreleased + + ## Version 1.1.0 + ...entries... + ``` + +2. **Bump the version** — in `gradle.properties`: + + ```properties + plugin_version=1.1.0 + ``` + +3. **Verify the build** (optional but recommended): + + ``` + ./gradlew build + ``` + +4. **Commit and tag** — the tag must be the version prefixed with `v`: + + ``` + git commit -am "Update: Plugin version 1.1.0 release" + git tag v1.1.0 + ``` + +5. **Push** — this is the publish step; the release workflow fires on the tag: + + ``` + git push && git push --tags + ``` + +6. **Check the result** — the `release` workflow under the repo's *Actions* tab builds the jar and creates the GitHub + Release. Verify the release page shows the changelog text and has `TriHunt-1.1.0.jar` attached. + +> **Never tag or push tags unless you have been explicitly asked to.** Pushing a tag publishes a release. + +## How the automation matches things up + +- The workflow strips the `v` from the tag (`v1.1.0` → `1.1.0`) and extracts everything between `## Version 1.1.0` and + the next `## ` heading in `CHANGELOG.md`. That text becomes the release body. +- **If no matching section exists, the workflow fails** — a release cannot ship with an empty changelog. Fix the heading + (exact match: `## Version 1.1.0`) and re-run the workflow, or delete and re-push the tag. +- The plugin jar from `build/libs/` is attached. + +## Fixing a botched release + +- **Wrong changelog / missing section**: fix `CHANGELOG.md`, commit, then move the tag and re-push it: + + ``` + git tag -f v1.1.0 + git push -f origin v1.1.0 + ``` + + Delete the draft/failed release on GitHub first if one was created. + +- **Wrong version in the jar**: you tagged before bumping `plugin_version`. Bump it, commit, move the tag as above. diff --git a/gradle.properties b/gradle.properties index 7fc6f1f..f180d5e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1,4 @@ kotlin.code.style=official + +# Plugin Properties +plugin_version=0.7.0 diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 5a61ee5..bb46476 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,6 +1,6 @@ name: TriHunt main: net.trilleo.mc.plugins.trihunt.Main -version: 0.7.0 +version: ${projectVersion} api-version: 1.21 description: Manhunt plugin for Minecraft. author: Trilleo