feat: stage 0, an empty RunicNPC that releases through CI
All checks were successful
PR Checks / plugin-checks (pull_request) Successful in -1m44s

The repository RunicNPC is built in (docs/runicnpc/PLAN.md §9, stage 0):

- plugin/RunicNPC.cs: `// Requires: Kits` (D217), `[Info]` with the 0.0.0
  placeholder the release stamps, `RunicNpc_ApiVersion()` (API 1), and
  `rnpc.status`, which reports the version and which hooks have fired. It
  spawns nothing.
- plugin.toml: the API version, the framework floors it was loaded on
  (Oxide 2.0.7726, Carbon 2.0.259) and requires_plugins = ["Kits"].
- scripts/checkPlugin.js, adapted from Rust-Plugins': every hook listed and
  void unless written down; chat-command signatures; every RunicNpc_ call
  reachable by Call (the HumanNPC trap, PLAN.md §1.2); ApiVersion,
  `// Requires:` and [Info] agreeing with plugin.toml. 23 self-tests, including
  the real plugin and a CRLF checkout.
- PR Checks on PRs into main and edge; the release workflow on main, with
  Rust-Plugins' release engine unchanged and an adapter that ships
  runicnpc-<ver>.tar.gz (runicnpc/RunicNPC.cs + manifest.json) and SHA256SUMS.
  No bundle dispatch until stage 4.
- tools/: the rig panel scripts, with the panel and server ids moved into a
  git-ignored tools/rigs.json. `con.js` became `console.js`: CON is a reserved
  device name on Windows, and git there cannot open the file.
- README, CONTRIBUTING (edge-based flow, AI disclosure, borrow-not-copy),
  SECURITY, the code of conduct, issue and PR templates.

`feat:` so the cutover to main cuts the first release, 0.1.0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
This commit is contained in:
2026-09-29 21:01:49 -05:00
parent 8641d8fb2e
commit 249f2e513f
19 changed files with 2027 additions and 4 deletions

107
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,107 @@
# 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 <noreply@anthropic.com>` or
`Assisted-By: <tool>`.
- 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.