Skip to main content
Thank you for your interest in contributing to Phichain! This guide will help you get started with contributing code, reporting bugs, and suggesting features.

Getting Started

1

Fork and clone

Fork the repository on GitHub and clone your fork:
git clone https://github.com/YOUR_USERNAME/phichain.git
cd phichain
2

Set up development environment

Follow the Building guide to set up Rust and dependencies.
cargo build
cargo test
3

Create a feature branch

Create a branch for your changes:
git checkout -b feature/your-feature-name
Use descriptive branch names:
  • feature/add-note-preview
  • fix/timeline-scroll-bug
  • docs/update-installation

Development Workflow

Making Changes

1

Write code

Make your changes following the code style guidelines below.
2

Format code

Format your code with rustfmt:
cargo fmt --all
3

Run lints

Check for issues with Clippy:
cargo clippy --all-features --all-targets -- -D warnings
4

Run tests

Ensure all tests pass:
cargo test
5

Test manually

Run the editor and test your changes:
cargo run -p phichain

Code Style

Phichain follows standard Rust conventions with some project-specific guidelines:

Formatting

  • Use cargo fmt for automatic formatting
  • 4 spaces for indentation (never tabs)
  • Maximum line length: 100 characters (flexible)

Naming Conventions

// Types: PascalCase
struct ChartNote { }
enum NoteType { }

// Functions and variables: snake_case
fn calculate_beat_time(beat: Beat) -> f64 { }
let note_position = calculate_position();

// Constants: SCREAMING_SNAKE_CASE
const MAX_NOTES_PER_LINE: usize = 1000;

// Modules: snake_case
mod timeline_editor;

Code Organization

  • Keep functions focused and small
  • Group related functionality into modules
  • Use mod.rs for module public interfaces
  • Document public APIs with doc comments

Documentation

Document public APIs using doc comments:
/// Calculates the time in seconds for a given beat.
///
/// # Arguments
///
/// * `beat` - The beat position to convert
/// * `bpm_list` - The BPM list containing tempo changes
///
/// # Returns
///
/// Time in seconds from the start of the chart
pub fn beat_to_time(beat: Beat, bpm_list: &BpmList) -> f64 {
    // Implementation
}

Bevy-Specific Guidelines

Certain Clippy lints are allowed in this project due to Bevy patterns.
Allowed lints:
  • type_complexity - Bevy queries can be complex
  • too_many_arguments - Bevy systems often have many parameters
System naming:
// Good: descriptive verb-based names
fn update_note_positions() { }
fn handle_input_events() { }
fn render_judgement_lines() { }

// Avoid: vague names
fn process() { }
fn update() { }
Resource and component patterns:
// Components: data only, no behavior
#[derive(Component)]
struct Note {
    beat: Beat,
    note_type: NoteType,
}

// Systems: behavior only, query components
fn spawn_notes(
    mut commands: Commands,
    chart: Res<Chart>,
    time: Res<GameTime>,
) {
    // Implementation
}

Testing

Write tests for new functionality:
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_beat_calculation() {
        let beat = Beat::new(1, 0, 4);
        assert_eq!(beat.to_f32(), 1.0);
    }
    
    #[test]
    fn test_bpm_change() {
        let mut bpm_list = BpmList::new();
        bpm_list.add(Beat::zero(), 120.0);
        assert_eq!(bpm_list.bpm_at(Beat::zero()), 120.0);
    }
}
All tests must pass before submitting a pull request. The CI will automatically run tests.

Commit Guidelines

Commit Message Format

Use clear, descriptive commit messages:
type: short description (50 chars or less)

Longer explanation if necessary. Wrap at 72 characters.
Explain what and why, not how.

- Bullet points are okay
- Use present tense ("add" not "added")

Commit Types

  • feat: New feature
  • fix: Bug fix
  • docs: Documentation changes
  • style: Code style changes (formatting, no logic change)
  • refactor: Code refactoring
  • perf: Performance improvements
  • test: Adding or updating tests
  • chore: Maintenance tasks, dependency updates

Examples

feat: add note preview in timeline

fix: correct beat calculation for negative BPM changes

docs: update building instructions for macOS

refactor: simplify event processing in game engine

Commit Best Practices

  • Make atomic commits (one logical change per commit)
  • Write descriptive messages
  • Reference issues when applicable: fix: resolve timeline crash (#123)
  • Keep commits focused and small

Pull Request Process

1

Ensure quality

Before creating a PR, verify:
  • Code is formatted (cargo fmt --all)
  • Clippy passes (cargo clippy --all-features --all-targets -- -D warnings)
  • All tests pass (cargo test)
  • Manual testing completed
  • Documentation updated if needed
2

Push your branch

Push your feature branch to your fork:
git push origin feature/your-feature-name
3

Create pull request

Create a PR on GitHub with a clear description:Title: Clear, concise summaryDescription:
## Summary
Brief description of changes

## Changes
- Added X feature
- Fixed Y bug
- Updated Z documentation

## Testing
- Tested on Windows/Linux/macOS
- Added unit tests for X
- Manual testing performed: ...

## Screenshots
(If applicable)

Fixes #123
4

Respond to feedback

Maintainers will review your PR. Address any feedback:
  • Make requested changes
  • Push updates to your branch
  • Respond to comments
  • Be patient and respectful
5

Merge

Once approved, a maintainer will merge your PR. Thank you for contributing!

PR Review Checklist

Reviewers will check:
  • Code quality and style
  • Tests are adequate
  • Documentation is updated
  • No unnecessary dependencies added
  • Performance impact considered
  • Breaking changes documented
  • Commit history is clean

Reporting Bugs

Before Reporting

1

Check existing issues

Search existing issues to avoid duplicates.
2

Verify it's a bug

Ensure it’s not expected behavior or a configuration issue.
3

Test on latest version

Verify the bug exists in the latest development build.

Bug Report Template

Include this information:
## Description
Clear description of the bug

## Steps to Reproduce
1. Open editor
2. Create new project
3. Click on timeline
4. Error occurs

## Expected Behavior
What should happen

## Actual Behavior
What actually happens

## Environment
- OS: Windows 11 / Ubuntu 22.04 / macOS 14
- Phichain version: 1.0.0-beta.5
- Rust version: 1.75.0

## Logs
(Attach relevant log output if available)

## Screenshots
(If applicable)

Suggesting Features

Feature Request Template

## Problem
What problem does this feature solve?

## Proposed Solution
How should it work?

## Alternatives Considered
Other ways to solve this problem

## Additional Context
Mockups, examples, or related features

Discussion First

For major features:
  1. Open a discussion or issue first
  2. Get feedback from maintainers
  3. Discuss implementation approach
  4. Then start coding

License

Phichain is licensed under LGPL-3.0 (GNU Lesser General Public License v3.0).

What This Means

By contributing, you agree that your contributions will be licensed under LGPL-3.0.
You can:
  • Use Phichain for any purpose
  • Study and modify the source code
  • Distribute copies
  • Distribute modified versions
You must:
  • Include the license and copyright notice
  • State changes made to the code
  • Disclose source code when distributing
  • Use the same license (LGPL-3.0)
LGPL allows linking with proprietary software, unlike GPL.The phichain-chart library can be used in closed-source projects if dynamically linked.

License Headers

No license headers are required in source files, but you may add them:
// Copyright (c) 2024 Phichain Contributors
// Licensed under LGPL-3.0

Community

Getting Help

Code of Conduct

Be respectful and constructive:
  • Welcome newcomers
  • Provide constructive feedback
  • Focus on ideas, not individuals
  • Respect different perspectives
  • Help maintain a positive environment

Development Tips

Use Bevy’s dynamic linking for faster compile times during development:
# Add to .cargo/config.toml
[target.x86_64-unknown-linux-gnu]
linker = "clang"
rustflags = ["-C", "link-arg=-fuse-ld=lld"]
Bevy supports hot-reloading. Modify assets in assets/ and see changes immediately.
Use Bevy’s logging system:
use bevy::prelude::*;

info!("Loading chart: {}", path);
warn!("Note outside valid range: {:?}", note);
error!("Failed to parse chart: {}", err);
Set log level with environment variable:
RUST_LOG=debug cargo run -p phichain
Use dbg!() for quick debugging:
let result = dbg!(calculate_beat_time(beat));
Or use a proper debugger (VSCode with rust-analyzer, CLion, etc.)
Use Bevy’s built-in diagnostics:
use bevy::diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin};

app.add_plugins((FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin::default()));

Areas Needing Help

Looking to contribute but not sure where to start? These areas always need help:

Documentation

  • API documentation
  • User guides
  • Code examples
  • Translations

Testing

  • Unit tests
  • Integration tests
  • Bug reports
  • Manual testing

Features

  • Check “good first issue” label
  • Implement planned features
  • Improve UX
  • Performance optimizations

Bug Fixes

  • Fix reported bugs
  • Improve error handling
  • Edge case handling
  • Platform-specific issues

Thank You!

Contributions of all kinds are appreciated:
  • Code contributions
  • Bug reports
  • Feature suggestions
  • Documentation improvements
  • Helping other users
  • Spreading the word
Every contribution helps make Phichain better for everyone.

View on GitHub

Check out the source code and start contributing