# Contributing to RunicNPC Thanks for your interest in contributing! This repository is **RunicNPC**, Runic Gateway's NPC plugin for Rust on Oxide and Carbon. What it will become, and in what order, is planned in [`docs/runicnpc/PLAN.md`](https://gitea.whitlocktech.com/RunicGateway/docs/src/branch/main/runicnpc/PLAN.md). Read it before proposing a feature: most are already placed in a stage. By participating you agree to abide by our [Code of Conduct](CODE_OF_CONDUCT.md). ## Ways to contribute - **Report a bug** or **request a feature** through the [issue tracker](https://gitea.whitlocktech.com/RunicGateway/runicnpc-rust/issues) (issue templates are provided). - **Improve the code or docs** by opening a pull request (see below). - **Never** report a security vulnerability in a public issue — see [SECURITY.md](SECURITY.md). ## Development setup The plugin is deployed as **source** and compiled by Oxide or Carbon at load. There is no standalone build and no CI build, because compiling it needs Rust's own managed assemblies. While developing, the loop is one copy and a wait: ```bash cp plugin/RunicNPC.cs /path/to/rust/oxide/plugins/ # or carbon/plugins/ # The framework notices the write, recompiles, and reloads. Watch its log. ``` That is a developer's loop, not how a server is set up: servers get RunicNPC from a release. A change that only works when you copy it by hand is a change that does not ship. **Borrow behaviours, never code.** RunicNPC may do what other NPC plugins do, but it is written from how Rust's own classes behave. NpcSpawn states no licence, so its source grants nothing and is read only as a description of what can be done (PLAN.md D214). Do not paste code from another plugin. ### Checks ```bash node scripts/checkPlugin.js node --test scripts/checkPlugin.test.js ``` Dependency-free; any Node 20+ runs them. They are what CI runs on every pull request, and what the release runs again on the commit it ships. `scripts/checkPlugin.js` explains each check in its header. Two matter most when you add code: - **A new hook goes in `ExpectedHooks`** in the plugin, so `rnpc.status` can report whether it fires. - **A hook that returns a value** changes what the game does. Add it to `ANSWERS_DELIBERATELY` in the checker with the reason, and make it answer for RunicNPC's own NPCs only, returning null for everything else on the server. ### Testing on a server A hook binds by reflection and fails silently, so a running server is the only proof that one fires. Every stage is tested on an **Oxide** server and then a **Carbon** server before it is merged. `tools/` holds the scaffolding used for that (see `tools/rigs.example.json`). ### Declarations `plugin.toml` and the plugin state some facts twice, and the checks hold them equal: | What | In the plugin | In `plugin.toml` | |---|---|---| | The API version | `ApiVersion` | `api` | | Required plugins | `// Requires:` lines | `requires_plugins` | Bump the API version in both, in the same change, when a `RunicNpc_*` call or a raised hook changes shape. ## Branch & PR workflow 1. Branch from an up-to-date **`edge`** with a descriptive name (`feat/…`, `fix/…`, `docs/…`, `chore/…`). 2. Keep changes focused; small PRs are easier to review. 3. Open a pull request against `edge`. Fill out the PR template, including the **AI-assisted contributions** disclosure. 4. A maintainer reviews it. `edge` is cut over to `main` for releases. ### Commit messages We use [Conventional Commits](https://www.conventionalcommits.org/) — `type(scope): summary` (e.g. `feat(api): add RunicNpc_Spawn`). The release version is derived from them: `feat` is a minor release, `fix` and `perf` a patch, `!` or `BREAKING CHANGE` a major; `docs`, `chore`, `ci` and `test` release nothing. ## AI-assisted contributions (disclosure required) This project is developed openly with AI assistance, and we ask the same transparency of everyone. **If you used an AI tool** (Claude, Copilot, ChatGPT, Cursor, etc.) to help produce a contribution, you must disclose it: - Tick the AI-usage box in the pull-request template and name the tool(s). - Mark AI-authored commits with a trailer, e.g. `Co-Authored-By: Claude ` or `Assisted-By: `. - You remain responsible for every line you submit: review it, understand it, and make sure it is correct and that you have the right to contribute it. Disclosed AI assistance is welcome. Undisclosed AI-generated contributions are not, and may be closed. ## License RunicNPC is licensed under the **GNU General Public License v3.0 or later** (see [LICENSE.md](LICENSE.md)). By submitting a contribution you agree that it is licensed under the same terms (inbound = outbound) and that you have the right to contribute it.