# Contributing to Runic Gateway — Oxide bridge plugin Thanks for your interest in contributing! This repo is the **C# Oxide side** of the Rust game bridge. The plugin dials out to the rust-link sidecar ([RunicGateway/Rust-Link](https://gitea.whitlocktech.com/RunicGateway/Rust-Link)) over a loopback TCP socket and speaks newline-delimited JSON over it. 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/Rust-Plugins/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 This plugin is deployed as **source** and compiled by Oxide at load — there is no standalone build artifact and no CI build, because compiling it needs Rust's own managed assemblies. See the [README](README.md) for the full model. **Key rule:** anything under `overlay/` is authoritative and mirrors the game server root. **Do not edit a file in a deployed server tree directly** — edit here under `overlay/` and copy it across. There is no `patches/` tier and there will not be one: Rust's server is a binary, so Oxide's published hook API is the only supported way in and there is nothing to diff against. While developing, the loop is one copy and a wait: ```bash cp overlay/oxide/plugins/RunicGateway.cs /path/to/rust/oxide/plugins/ # Oxide notices the write, recompiles, and reloads. Watch oxide/logs/. ``` That is a developer's loop and not how a server is set up: operators run the [Runic Gateway installer](https://gitea.whitlocktech.com/RunicGateway/installer), which syncs the released overlay tarball and installs the sidecar alongside it. A change reaches a server through a release, so a change that only works when you copy it by hand is a change that does not ship. - `overlay/` — mirrors the game server root; the only thing that is deployed. - `overlay.toml` — release metadata, including the protocol version the installer pairs on. ### Testing **A hook binds by reflection and fails silently**, so a running server is the only proof that one fires. There is no unit-test harness here and adding one would only ever test the harness. What the plugin gives you instead is a console command: ``` rg.link ``` It reports the link's own counters — connected, queue depth, sent, dropped, received, reconnects, write errors and the boot id. It is the first thing to ask for when the website says a server is offline, and it answers over RCON as well as at the console. ### Protocol compatibility The loopback JSON protocol is a **compatibility contract** shared with the sidecar. The canonical event/command catalogue lives in the [docs repo](https://gitea.whitlocktech.com/RunicGateway/docs/src/branch/main/rust-link) (`PROTOCOL.md`). If you add or change an event or a command, keep all of these in sync in ONE change: | What | Where | |---|---| | the emitter or handler | `overlay/oxide/plugins/RunicGateway.cs` | | `protocol` | `overlay.toml`, this repo | | `PROTOCOL_VERSION` | `sidecar/src/main.rs`, Rust-Link | | `PROTOCOL_VERSION` | `server/sidecarClient.js`, Module-Rust | | the spec | `rust-link/PROTOCOL.md`, docs | The installer refuses to pair a sidecar and an overlay whose numbers disagree, so a bump that lands in one repo and not the others does not silently half-deploy — it fails to compose at all, which is the intended outcome. ## Branch & PR workflow 1. Branch from `main` with a descriptive name (`feature/…`, `fix/…`, `docs/…`, `chore/…`). 2. Keep changes focused; small PRs are easier to review. 3. Push and open a pull request against `main`. Fill out the PR template, including the **AI-assisted contributions** disclosure. 4. A maintainer will review; address feedback with follow-up commits. ### Commit messages We use [Conventional Commits](https://www.conventionalcommits.org/) — `type(scope): summary` (e.g. `feat(bridge): add clan.roster event`). ## 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 Runic Gateway 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.