Thank you for your interest in contributing! This document explains the process.
- Code of Conduct
- Development Lifecycle
- How to Contribute
- Development Setup
- Architecture
- Design Principles
- Commit Style
- Pull Request Process
- Testing
- Release Process
- Continuous Improvement
This project follows the Contributor Covenant. Be respectful and constructive.
Every change in oxidized-client-headless follows a structured lifecycle:
Identify → Research → Decide → Plan → Test First → Implement → Review → Integrate → Retrospect
The lifecycle ensures that we:
- Understand the problem before writing code
- Write tests before implementation (TDD)
- Actively identify improvements during review
For trivial changes (typo fixes, dependency bumps), an abbreviated lifecycle applies.
| Type | How |
|---|---|
| 🐛 Bug report | Open a bug report issue |
| 💡 Feature request | Open a feature request issue |
| 📖 Docs | Edit any .md file and open a PR |
| 🧩 Implementation | Pick an open issue and open a PR |
| 🔍 Review | Review open PRs and leave constructive feedback |
| 💡 Improvement | Found a better approach? Open an issue or PR |
# 1. Fork and clone
git clone https://github.com/oxidized-mc/client-headless.git
cd client-headless
# 2. Rust stable (toolchain pinned via rust-toolchain.toml)
rustup update stable
# 3. Build
cargo build
# 4. Run tests
cargo test
# 5. Check formatting and lints
cargo fmt --check
cargo clippy --all-targets -- -D warningscargo install cargo-deny # licence + advisory checks
cargo install cargo-nextest # faster test runner
cargo install cargo-watch # auto-rebuild on saveoxidized-client-headless is a single crate. Low-level protocol primitives (codec, NBT, types, chat, crypto, compression, transport, auth) are provided by the shared oxidized-mc crate ecosystem. This crate focuses on client-specific logic: connection management, world state, and bot behavior.
Reference code: The decompiled vanilla client/server lives in mc-server-ref/decompiled/
(gitignored). When implementing something, always check the Java reference first.
Rewrite idiomatically in Rust — do not transliterate Java line-by-line.
Key principle: the wire protocol is sacred (we can't change what the server sends or expects), but everything client-side uses modern, idiomatic Rust design rather than cloning vanilla Java patterns.
All commits must follow Conventional Commits:
<type>(<scope>): <short description>
| Type | When | Version bump |
|---|---|---|
feat |
New user-visible feature | Minor |
fix |
Bug fix | Patch |
perf |
Performance improvement | Patch |
refactor |
Restructure, no behaviour change | None |
test |
Tests only | None |
docs |
Documentation only | None |
chore |
Dependencies, CI, tooling | None |
ci |
CI/CD workflow changes | None |
Use a descriptive scope when relevant (e.g., client, world, bot).
Use ci for workflow files, deps for dependency updates.
feat(client): implement connection builder
fix: correct session token refresh logic
perf: cache chunk sections to avoid recomputation
test: add NBT round-trip tests for all 13 tag types
chore(deps): bump tokio from 1.43 to 1.44
Breaking changes: add ! after type or add BREAKING CHANGE: footer.
- Create a branch:
git checkout -b feat/varint-codec - Make your changes following the lifecycle
- Commit with conventional commits
- Open a PR targeting
main; fill in the PR template completely - At least one approving review is required before merge
- Squash-merge preferred for feature branches
Reviews are not just about catching bugs — they actively seek improvements:
- Does the code follow the project's design principles?
- Could any existing pattern be improved?
- Are there learnings to record?
- Unit tests live next to the code in
#[cfg(test)]modules - Integration tests live in
tests/ - All public API must have at least one test
- Test modules use
#[allow(clippy::unwrap_used, clippy::expect_used)]for assertion-like code - Reference the Java behaviour when writing expected values:
// VarInt encoding mirrors net.minecraft.network.VarInt in the reference assert_eq!(encode_varint(300), &[0xAC, 0x02]);
Run with nextest for faster feedback:
cargo nextest run --workspaceCriterion benchmarks live in
benches/. Run the full suite:
cargo bench --workspaceoxidized-client-headless uses automated versioning and release management based on conventional commits.
- Commit with conventional prefixes —
feat,fix,perf, etc. - release-please automatically creates and maintains a "Release PR" on GitHub that accumulates changes and proposes the next version bump.
- When a maintainer merges the Release PR, a git tag (
v0.X.Y) and GitHub Release are created automatically.
| Commit prefix | Bump |
|---|---|
feat!: or BREAKING CHANGE: footer |
Minor (pre-1.0) / Major (post-1.0) |
feat(scope): |
Minor |
fix(scope):, perf(scope): |
Patch |
refactor, test, docs, chore, ci |
No version bump |
We believe the codebase should always be getting better.
After every milestone:
- Conduct a retrospective
- Record learnings and identify improvements
- Record any technical debt incurred
During every PR review:
- Identify outdated patterns or decisions
- Look for patterns that should be extracted or formalized
- Suggest improvements (not just catch bugs)
When you find something better:
- Don't just note it — act on it
- Open an issue or PR
- Plan and execute the refactoring