EU-Utility/CONTRIBUTING.md

11 KiB

Contributing to EU-Utility

First off, thank you for considering contributing to EU-Utility! It's people like you that make this tool better for the entire Entropia Universe community.

Table of Contents


Code of Conduct

This project and everyone participating in it is governed by our commitment to:

  • Be respectful - Treat everyone with respect. Healthy debate is encouraged, but harassment is not tolerated.
  • Be constructive - Provide constructive feedback and be open to receiving it.
  • Be inclusive - Welcome newcomers and help them get started.
  • Focus on what's best - Consider what is best for the community and the project.

Getting Started

Prerequisites

  • Python 3.11 or higher
  • Git
  • A GitHub account
  • Entropia Universe (for testing game integration features)

Quick Setup

# 1. Fork the repository on GitHub
# 2. Clone your fork
git clone https://github.com/YOUR_USERNAME/EU-Utility.git
cd EU-Utility

# 3. Add upstream remote
git remote add upstream https://github.com/ImpulsiveFPS/EU-Utility.git

# 4. Create virtual environment
python -m venv venv

# 5. Activate it
# Windows:
venv\Scripts\activate
# Linux/Mac:
source venv/bin/activate

# 6. Install dependencies
pip install -r requirements.txt

# 7. Run tests
python -m pytest

# 8. Start EU-Utility
python -m core.main

How Can I Contribute?

🐛 Report Bugs

Before creating a bug report, please check the existing issues to avoid duplicates.

When creating a bug report, include:

  • Clear title - Summarize the issue
  • Steps to reproduce - Detailed steps to recreate the bug
  • Expected behavior - What should have happened
  • Actual behavior - What actually happened
  • Screenshots - If applicable
  • System info:
    • OS and version
    • Python version
    • EU-Utility version
    • Error messages/logs

💡 Suggest Enhancements

Enhancement suggestions are welcome! Please provide:

  • Clear description - What would you like to see?
  • Use case - Why would this be useful?
  • Proposed implementation - How could it work? (optional)

🔌 Create Plugins

Plugins are the heart of EU-Utility! Create and share your own:

📝 Improve Documentation

Documentation improvements are always welcome:

  • Fix typos and grammar
  • Add examples and clarifications
  • Translate to other languages
  • Update outdated information

🧪 Write Tests

Help improve code quality by adding tests:

  • Unit tests for core functionality
  • Integration tests for plugins
  • Performance benchmarks

🔧 Fix Issues

Look for issues labeled:

  • good first issue - Great for newcomers
  • help wanted - Extra attention needed
  • bug - Something isn't working
  • enhancement - New features

Development Setup

Project Structure

EU-Utility/
├── core/                  # Core services
│   ├── main.py           # Application entry point
│   ├── plugin_manager.py # Plugin management
│   ├── event_bus.py      # Event system
│   ├── nexus_api.py      # Nexus integration
│   └── ...
├── plugins/              # Plugin directory
│   ├── base_plugin.py    # Base plugin class
│   ├── dashboard/        # Dashboard plugin
│   ├── loot_tracker/     # Loot tracker plugin
│   └── ...
├── docs/                 # Documentation
├── tests/                # Test suite
├── data/                 # User data (not in repo)
└── assets/               # Images, icons, sounds

Development Workflow

# 1. Sync with upstream
git fetch upstream
git checkout main
git merge upstream/main

# 2. Create feature branch
git checkout -b feature/my-feature

# 3. Make changes
# ... edit files ...

# 4. Test changes
python -m pytest
python -m core.main

# 5. Commit changes
git add .
git commit -m "feat: add my feature"

# 6. Push to fork
git push origin feature/my-feature

# 7. Create Pull Request on GitHub

Plugin Development

Creating a New Plugin

  1. Create plugin directory:
mkdir plugins/my_plugin
touch plugins/my_plugin/__init__.py
touch plugins/my_plugin/plugin.py
  1. Implement the plugin:
# plugins/my_plugin/plugin.py
from plugins.base_plugin import BasePlugin

class MyPlugin(BasePlugin):
    name = "My Plugin"
    version = "1.0.0"
    author = "Your Name"
    description = "What it does"
    
    def initialize(self):
        pass
    
    def get_ui(self):
        # Return QWidget
        pass
  1. Test thoroughly:

    • Test UI rendering
    • Test hotkey functionality
    • Test data persistence
    • Test error handling
  2. Add documentation:

    • Plugin README.md
    • Code comments
    • Usage examples

Plugin Guidelines

Do:

  • Use existing core services
  • Follow naming conventions
  • Add proper error handling
  • Clean up resources in shutdown()
  • Use background tasks for heavy operations
  • Follow the style guide

Don't:

  • Block the main thread
  • Access game files directly
  • Hardcode paths
  • Ignore errors silently
  • Duplicate existing functionality

Style Guidelines

Python Code Style

We follow PEP 8 with some additions:

"""
EU-Utility - Module Name

Short description of the module.

Features:
- Feature 1
- Feature 2
"""

from typing import Optional, Dict, Any, List
from dataclasses import dataclass

# Constants
MAX_RETRIES = 3
DEFAULT_TIMEOUT = 30


@dataclass
class Config:
    """Configuration data class."""
    name: str
    value: int
    enabled: bool = True


class MyClass:
    """
    Brief description of the class.
    
    Longer description with usage examples.
    
    Attributes:
        name: The name attribute
        value: The value attribute
    
    Example:
        >>> obj = MyClass("test", 42)
        >>> obj.process()
    """
    
    def __init__(self, name: str, value: int) -> None:
        """Initialize the class."""
        self.name = name
        self.value = value
        self._private_var = None
    
    def process(self, data: Dict[str, Any]) -> Optional[str]:
        """
        Process the data.
        
        Args:
            data: Input data dictionary
            
        Returns:
            Processed string or None if invalid
            
        Raises:
            ValueError: If data is invalid
        """
        if not data:
            raise ValueError("Data cannot be empty")
        
        return f"{self.name}: {self.value}"

UI Style Guide

Use the EU-Utility theme:

# Colors
BG_DARK = "#1a1a1a"       # Main background
BG_PANEL = "#2a2a2a"      # Panel background
ACCENT_ORANGE = "#ff8c42" # Accent color
TEXT_WHITE = "#ffffff"    # Primary text
TEXT_MUTED = "rgba(255,255,255,150)"  # Secondary text

# Apply to widgets
widget.setStyleSheet(f"""
    QWidget {{
        background-color: {BG_DARK};
        color: {TEXT_WHITE};
    }}
""")

Documentation Style

  • Use clear, concise language
  • Include code examples
  • Document all public methods
  • Use type hints
  • Keep line length under 100 characters

Commit Messages

We follow Conventional Commits:

<type>(<scope>): <subject>

<body>

<footer>

Types

  • feat - New feature
  • fix - Bug fix
  • docs - Documentation only
  • style - Code style (formatting, no logic change)
  • refactor - Code refactoring
  • perf - Performance improvements
  • test - Adding tests
  • chore - Maintenance tasks

Examples

feat(plugins): add auction tracker plugin

Add new plugin for tracking auction prices and markups.
Features:
- Real-time price tracking
- Historical data charts
- Markup calculations

Closes #123
fix(ocr): resolve memory leak in capture method

The OCR service was not releasing image buffers,
causing memory usage to grow over time.

Fixes #456
docs(readme): update installation instructions

Add Windows 11 specific steps and troubleshoot
tips for common installation issues.

Pull Request Process

  1. Update documentation - Update README.md, CHANGELOG.md, or docs/ if needed
  2. Add tests - Include tests for new functionality
  3. Update CHANGELOG.md - Add your changes under the [Unreleased] section
  4. Ensure tests pass - Run python -m pytest
  5. Fill out PR template - Describe what and why
  6. Request review - Wait for maintainer review
  7. Address feedback - Make requested changes
  8. Merge - Maintainers will merge when ready

PR Checklist

  • Code follows style guidelines
  • Tests pass locally
  • Documentation updated
  • CHANGELOG.md updated
  • Commit messages follow conventions
  • PR description is clear

Reporting Bugs

Before Submitting

Bug Report Template

**Description**
Clear description of the bug.

**To Reproduce**
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error

**Expected Behavior**
What should have happened.

**Screenshots**
If applicable, add screenshots.

**Environment:**
- OS: [e.g., Windows 11]
- Python: [e.g., 3.11.4]
- EU-Utility: [e.g., 2.0.0]

**Logs:**

Paste relevant log output


**Additional Context**
Any other information.

Suggesting Enhancements

Enhancement Template

**Feature Request**
Clear description of the feature.

**Problem/Motivation**
What problem does this solve?

**Proposed Solution**
How should it work?

**Alternatives**
Other approaches considered.

**Additional Context**
Mockups, examples, etc.

Community

Communication Channels

  • GitHub Issues - Bug reports and feature requests
  • GitHub Discussions - General discussion and Q&A
  • Discord - Real-time chat (link TBD)

Recognition

Contributors will be:

  • Listed in CONTRIBUTORS.md
  • Mentioned in release notes
  • Credited in relevant documentation

Development Tips

Debugging

# Enable debug logging
import logging
logging.basicConfig(level=logging.DEBUG)

# Add to your plugin
self.log_debug("Debug information")

Testing Plugins

# tests/test_my_plugin.py
import pytest
from plugins.my_plugin.plugin import MyPlugin

class TestMyPlugin:
    def test_initialization(self):
        plugin = MyPlugin()
        plugin.initialize()
        assert plugin.name == "My Plugin"

Profiling

# Profile plugin performance
import cProfile
import pstats

profiler = cProfile.Profile()
profiler.enable()

# Your code here

profiler.disable()
stats = pstats.Stats(profiler)
stats.sort_stats('cumtime')
stats.print_stats(20)

Questions?

If you have questions:

  1. Check the documentation
  2. Search existing issues
  3. Ask in GitHub Discussions
  4. Join our Discord

Thank you for contributing to EU-Utility! 🎮