Thank you for your interest in contributing to MCOS (Motor City Online Server)! This document provides guidelines for contributing to the project.
- Node.js 20+ with npm
- PostgreSQL 14+
- Docker (optional, for development services)
# Clone the repository
git clone https://github.com/rustymotors/mcos.git
cd mcos
# Install dependencies
make install
# Start development services (PostgreSQL, etc.)
make up
# Run database migrations
make migration-up
# Start the server
make startFor detailed setup instructions, see CLAUDE.md.
This project uses Biome for linting and formatting:
# Format all files
npm run format:all
# Lint all files
npm run lint:all
# Type check all packages
npm run check:all- Use strict TypeScript compilation
- ES modules (
import/export, notrequire) - Explicit types for function parameters and return values
- Prefer interfaces over type aliases for object shapes
- Each package has its own
tsconfig.jsonextendingtsconfig.base.json - Use project references for cross-package dependencies
- Keep files focused on a single responsibility
mcos/
├── packages/ # Service packages
│ ├── gateway/ # Main server orchestration
│ ├── lobby/ # Lobby management (port 7003)
│ ├── login/ # Authentication (port 8226)
│ ├── persona/ # Character profiles (port 8228)
│ ├── shared/ # Common utilities
│ └── transactions/ # MCOTS protocol (port 43300)
├── libs/ # Library packages
│ └── @rustymotors/
│ ├── binary/ # Serialization
│ ├── protocol/ # Protocol definitions
│ └── parser/ # Message parsing
├── docs/ # Documentation
│ ├── protocol/ # Protocol documentation
│ └── handlers/ # Handler guides
└── migrations/ # Database migrations
See the detailed guide: docs/handlers/ADDING_HANDLERS.md
Quick steps:
- Create handler function in appropriate service package
- Define packet structure with
setSerializeOrder() - Implement handler logic
- Register in service registry
See: docs/protocol/PACKET_SERIALIZATION.md
Key classes:
BytableMessage- Main message classBytableFieldTypes- Available field typesMessageHandlerRegistry- Handler registration
- Create migration in
migrations/directory - Run
npm run migrateto apply - Update types with
npm run types
# Run all tests with coverage
npm run coverage
# Run tests without coverage
npm test
# Run session replay tests
npm run test:session
# Run package-specific tests
npm run test:packages- Use Vitest for testing
- Place tests in
__tests__/directories or*.test.tsfiles - Mock external dependencies using
vi.mock() - Use
createTestContext()for handler testing
Record live traffic for replay testing:
RECORD_SESSIONS=true npm startSessions are saved to test/fixtures/sessions/.
- Ensure all tests pass:
npm test - Ensure type checking passes:
npm run check:all - Ensure linting passes:
npm run lint:all - Format code:
npm run format:all
- Create a feature branch from
dev - Write clear commit messages
- Include tests for new functionality
- Update documentation as needed
- Keep PRs focused on a single change
Use clear, descriptive commit messages:
Add PT_OPEN_COMM_CHANNEL handler for lobby service
- Implement channel grant response
- Add user joined notification
- Register handler in lobby registry
This project follows SOLID principles:
- Single Responsibility: Each class/module has one purpose
- Open/Closed: Use registries for extensibility
- Liskov Substitution: Handlers implement consistent interfaces
- Interface Segregation: Focused interfaces (ISessionStore, etc.)
- Dependency Inversion: Inject abstractions via DatabaseProvider
- Check existing documentation in
docs/ - Review CLAUDE.md for project overview
- Open an issue for questions or bugs
- Join discussions in pull requests
By contributing, you agree that your contributions will be licensed under the GNU AGPL v3 license.