minecraft-paper-plugin

📁 sun-mc-dev/claude-minecraft-skill 📅 5 days ago
3
总安装量
3
周安装量
#61097
全站排名
安装命令
npx skills add https://github.com/sun-mc-dev/claude-minecraft-skill --skill minecraft-paper-plugin

Agent 安装分布

github-copilot 3
codex 3
kimi-cli 3
gemini-cli 3
cursor 3
amp 3

Skill 文档

Minecraft Paper Plugin Development Skill

Trigger Phrase

This skill activates when the user says “Gigi Aki” followed by their plugin requirements.

Overview

Create production-ready Minecraft Paper plugins following modern best practices:

  • Modern Paper API: No deprecated methods, use latest Paper-specific features
  • PacketEvents: Packet manipulation for custom mechanics and anti-cheat
  • Async & Multi-threaded: Non-blocking operations, proper scheduler usage
  • High Performance: Optimized code, caching, minimal allocations
  • Flexible Database: Support SQLite (default), MySQL, PostgreSQL, MongoDB, Redis
  • Type-safe Configuration: YAML (default) or JSON with validation
  • Modern Dependencies: Lombok, HikariCP, Reflections, Gson, Adventure API
  • Complete Developer API: Full API system for other plugins to integrate
  • Professional Documentation: Auto-generated README.md, API docs, contribution guides
  • GitHub Ready: CI/CD workflows, issue templates, changelog, code of conduct
  • Unit Testing: JUnit 5 test structure with examples
  • Code Quality: EditorConfig, consistent formatting, best practices

Development Workflow

1. Analyze Requirements

When user says “Gigi Aki” + requirements:

  1. Identify plugin type (combat, economy, game mechanic, anti-cheat, etc.)
  2. Determine complexity and required features
  3. Choose appropriate architecture patterns
  4. Select database type (default SQLite unless specified)
  5. Choose build system (Maven default, Gradle if multi-module)
  6. Determine Java version (Java 21 for modern, Java 8 for legacy 1.8)

1.5. Interactive Requirements Gathering

IMPORTANT: Before implementing, engage in a detailed requirements gathering session like an experienced developer. Ask clarifying questions to understand the full scope and details. Think like a senior Java developer with 25 years of experience who needs complete specifications before writing production code.

Core Functionality Questions

For ANY plugin type, ask:

  1. Target server version: “What Minecraft version are you targeting?” (1.21.x, 1.20.x, 1.8.8, etc.)
  2. Scale and performance: “How many players will this handle concurrently?” (affects architecture decisions)
  3. Persistence requirements: “What data needs to be saved?” (player stats, configurations, logs, etc.)
  4. Multi-server support: “Will this run on a single server or network (BungeeCord/Velocity)?”

Plugin-Specific Deep Dive Questions

For Combat Plugins:

  • “What combat mechanics do you want to modify?” (knockback, damage, cooldowns, combos, hit detection)
  • “Should it work with vanilla combat or completely override it?”
  • “Any specific formulas for damage/knockback calculations?”
  • “Do you need hitbox manipulation or just damage/velocity modification?”
  • “Should there be weapon-specific mechanics?” (swords vs axes vs bows)
  • “Any particle effects or sound effects for hits?”
  • “Do you need combat logging prevention? How long is the combat tag?”
  • “Should there be different modes/arenas with different rules?”

For Economy Plugins:

  • “What currency system?” (single currency, multiple currencies, item-based)
  • “Starting balance for new players?”
  • “Transaction types needed?” (player-to-player, player-to-shop, admin commands)
  • “Should there be a transaction fee/tax system?”
  • “Do you need bank accounts, or just wallet balances?”
  • “Interest on balances? Offline earning?”
  • “Integration with existing plugins?” (Vault API, other economy plugins)
  • “Admin tools needed?” (set balance, add/remove money, transaction history, economy reset)
  • “GUI shops or command-based?”

For Anti-Cheat Plugins:

  • “Which specific cheats to detect?” (killaura, reach, speed, fly, scaffold, etc.)
  • “Detection approach?” (statistical analysis, pattern matching, threshold-based)
  • “What actions on violation?” (kick, ban, notify admins, rollback, reduce damage)
  • “Violation decay system?” (violations expire after time)
  • “Bypass permissions for staff?”
  • “Should it log to database for analysis?”
  • “Integration with existing ban plugins?”
  • “False positive handling – how strict vs lenient?”
  • “Client brand/mod detection?”

For Parkour Plugins:

  • “Checkpoint system?” (automatic, manual, pressure plates)
  • “How to define parkour courses?” (worldedit selection, config, in-game commands)
  • “Leaderboard requirements?” (per-course, global, time-based, completion-based)
  • “Rewards system?” (money, items, permissions on completion)
  • “Practice mode vs competitive mode?”
  • “Spectator system for other players?”
  • “Reset mechanism?” (command, automatic on fall, checkpoint rollback)
  • “Time tracking precision?” (milliseconds, seconds)

For Game Mechanic Plugins:

  • “What’s the core game loop?”
  • “Win/loss conditions?”
  • “Team system or free-for-all?”
  • “Lobby system needed?”
  • “Game phases?” (waiting, starting, active, ending)
  • “Arena/map management?”
  • “Spectator mode?”
  • “Statistics tracking?”

For Shop/GUI Plugins:

  • “Item categories and organization?”
  • “Dynamic pricing or fixed?”
  • “Stock limits? Cooldowns?”
  • “Permission-based access to items?”
  • “Sell-back system?”
  • “GUI layout preferences?” (chest size, navigation style)
  • “Search functionality?”
  • “Transaction confirmation dialogs?”

Architecture and Technical Questions

Always ask:

  1. Commands structure: “What commands are needed? Include aliases, permissions, and usage examples.”
  2. Permissions hierarchy: “How should permissions be organized?” (admin, moderator, user tiers)
  3. Configuration flexibility: “What should be configurable vs hard-coded?”
  4. API exposure: “Will other plugins need to hook into this? Need a developer API?”
  5. Event priorities: “Any specific event handling priorities or conflicts with other plugins?”
  6. Placeholder support: “Need PlaceholderAPI integration for displaying data?”
  7. Locale/i18n: “Multiple languages needed? What’s the default?”

Performance and Scalability Questions

For production plugins, ask:

  1. Expected TPS impact: “What’s your performance budget? Target TPS with plugin active?”
  2. Data volume: “How much data per player? How many players?”
  3. Caching strategy: “What data should be cached in memory vs fetched from DB?”
  4. Async requirements: “Which operations MUST be async?” (database writes, external API calls)
  5. Batch processing: “Any bulk operations that need optimization?”

Example Complete Requirements Session

User: “Gigi Aki – create a custom knockback plugin”

Assistant: “I’ll create a professional knockback plugin for you. Let me gather some details to ensure it meets your exact needs:

Core Functionality:

  1. What Minecraft version are you targeting?
  2. Should this modify vanilla knockback or completely override it?
  3. What parameters do you want to configure? (horizontal multiplier, vertical multiplier, per-world settings, per-weapon settings)
  4. Do you need different knockback profiles (PvP mode, practice mode, etc.)?

Packet Implementation: 5. Should I use PacketEvents for precise velocity control, or modify through Bukkit events? 6. Do you want client-side prediction compensation?

Features: 7. Should knockback vary by weapon type? (swords, axes, custom items) 8. Do you need sprint/velocity multipliers? 9. Any special effects? (particles, sounds on hit) 10. Need a test command for admins to try different values live?

Data & Permissions: 11. Should player preferences be saved? (players can choose their knockback style) 12. Permission nodes for bypassing custom knockback? 13. Any integration with combat plugins or anti-cheat?

Performance: 14. How many players will be in combat simultaneously? 15. Should calculations be cached or computed per-hit?

Once you provide these details, I’ll create a production-ready plugin with complete implementation, no placeholders.”

Requirements Documentation

After gathering requirements, create a brief summary before implementation:

=== PLUGIN REQUIREMENTS SUMMARY ===
Type: [Combat/Economy/etc.]
Target Version: [1.21.3/1.8.8/etc.]
Java Version: [21/8]
Build Tool: [Maven/Gradle]
Database: [SQLite/MySQL/etc.]

Core Features:
- Feature 1: [detailed description]
- Feature 2: [detailed description]

Commands:
- /command1 <args> - Description [permission.node]

Configuration:
- setting1: default value
- setting2: default value

Performance Requirements:
- Max players: X
- Data per player: Y
- Async operations: [list]

Special Considerations:
- [any unique requirements]
===================================

This ensures both you and the user are aligned before writing a single line of code.

2. Load Relevant References

Based on plugin requirements, read appropriate reference files:

  • Always read:
    • references/professional-template.md for project structure, README, API, GitHub setup
    • references/paper-api-patterns.md for modern Paper API usage
  • For packet manipulation: references/packetevents-patterns.md
  • For database features: references/database-patterns.md
  • For configuration: references/config-patterns.md
  • For Maven projects: references/maven-template.md
  • For Gradle projects: references/gradle-template.md

3. Create Complete Implementation

Generate full plugin structure with:

Project Files

Maven Project (Default):

plugin-name/
├── .github/
│   ├── workflows/
│   │   ├── build.yml           # CI/CD build pipeline
│   │   └── release.yml         # Release automation
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md       # Bug report template
│   │   └── feature_request.md  # Feature request template
│   └── dependabot.yml          # Dependency updates
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── [package]/
│   │   │       ├── PluginName.java        # Main plugin class
│   │   │       ├── api/                   # Public API package
│   │   │       │   ├── PluginNameAPI.java
│   │   │       │   ├── events/            # Custom events
│   │   │       │   ├── managers/          # Manager interfaces
│   │   │       │   └── data/              # Data classes
│   │   │       ├── commands/              # Command classes
│   │   │       ├── listeners/             # Event listeners
│   │   │       ├── managers/              # Manager implementations
│   │   │       ├── database/              # Database layer
│   │   │       ├── config/                # Configuration
│   │   │       └── util/                  # Utilities
│   │   └── resources/
│   │       ├── plugin.yml
│   │       ├── config.yml
│   │       └── messages.yml               # i18n messages
│   └── test/
│       └── java/
│           └── [package]/
│               └── PluginNameTest.java    # Unit tests
├── .editorconfig              # Code style consistency
├── .gitignore                 # Git ignore rules
├── CHANGELOG.md               # Version history
├── CODE_OF_CONDUCT.md         # Community guidelines
├── CONTRIBUTING.md            # Contribution guide
├── LICENSE                    # MIT License
├── README.md                  # Project documentation
└── pom.xml                    # Maven configuration

Gradle Project (for Kotlin or multi-module):

plugin-name/
├── build.gradle.kts
├── settings.gradle.kts
├── gradle/
│   └── libs.versions.toml
└── src/ (same structure as Maven)

Essential Files to Generate

CRITICAL: Every plugin MUST include these files for a professional project:

  1. README.md – Complete project documentation (see professional-template.md)
  2. API Package – Full developer API with:
    • api/PluginNameAPI.java (interface)
    • PluginNameAPIImpl.java (implementation, package-private)
    • api/events/ (custom events)
    • api/managers/ (manager interfaces)
  3. GitHub Workflows:
    • .github/workflows/build.yml (CI/CD)
    • .github/workflows/release.yml (auto-releases)
  4. Issue Templates:
    • .github/ISSUE_TEMPLATE/bug_report.md
    • .github/ISSUE_TEMPLATE/feature_request.md
  5. Contributing Files:
    • CONTRIBUTING.md
    • CODE_OF_CONDUCT.md
    • CHANGELOG.md
  6. Code Quality:
    • .editorconfig
    • .gitignore
  7. Unit Tests:
    • src/test/java/.../PluginNameTest.java
  8. LICENSE – MIT License

Reference: See references/professional-template.md for complete templates of all these files.

Core Components

Main Plugin Class (with API integration):

@Getter
public class PluginName extends JavaPlugin {
    @Getter
    private static PluginName instance;
    
    @Getter
    private static PluginNameAPI api;
    
    private ConfigManager<PluginConfig> configManager;
    private DatabaseManager database;
    
    @Override
    public void onLoad() {
        instance = this;
        // Initialize PacketEvents
        PacketEvents.setAPI(SpigotPacketEventsBuilder.build(this));
        PacketEvents.getAPI().load();
    }
    
    @Override
    public void onEnable() {
        long startTime = System.currentTimeMillis();
        
        try {
            // Initialize PacketEvents
            PacketEvents.getAPI().init();
            
            // Load configuration
            configManager = new YamlConfigManager(this);
            PluginConfig config = configManager.get();
            
            // Validate configuration
            if (!ConfigValidator.validate(config, this)) {
                getLogger().severe("Invalid configuration!");
                getServer().getPluginManager().disablePlugin(this);
                return;
            }
            
            // Initialize database
            database = DatabaseFactory.create(this, getConfig());
            database.initialize().join();
            
            // Register listeners
            registerListeners();
            
            // Register commands
        registerCommands();
        
        // Start async tasks
        startTasks();
        
        // Initialize API (last step, after all managers are ready)
        api = new PluginNameAPIImpl();
        
        long loadTime = System.currentTimeMillis() - startTime;
        getLogger().info("Plugin enabled successfully in " + loadTime + "ms!");
        } catch (Exception e) {
            getLogger().log(Level.SEVERE, "Failed to enable plugin!", e);
            getServer().getPluginManager().disablePlugin(this);
        }
    }
    
    @Override
    public void onDisable() {
        getLogger().info("Disabling plugin...");
        
        // Shutdown PacketEvents
        PacketEvents.getAPI().terminate();
        
        // Shutdown database (save all data synchronously)
        if (database != null) {
            database.shutdown().join();
        }
        
        getLogger().info("Plugin disabled successfully!");
    }
    
    private void registerListeners() {
        // Bukkit listeners
        getServer().getPluginManager().registerEvents(new YourListener(this), this);
        
        // PacketEvents listeners
        PacketEvents.getAPI().getEventManager().registerListener(new YourPacketListener(this));
    }
    
    private void registerCommands() {
        // Register commands
    }
    
    private void startTasks() {
        // Start async repeating tasks
    }
}

4. Implementation Guidelines

Always Use Modern APIs

// CORRECT - Modern Paper scheduler
plugin.getServer().getAsyncScheduler().runNow(plugin, task -> {
    // Async work
});

// WRONG - Deprecated BukkitScheduler
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {});

Packet-Based Features

For custom mechanics, use PacketEvents:

public class CustomKnockbackListener extends PacketListenerAbstract {
    @Override
    public void onPacketSend(PacketSendEvent event) {
        if (event.getPacketType() == PacketType.Play.Server.ENTITY_VELOCITY) {
            WrapperPlayServerEntityVelocity packet = 
                new WrapperPlayServerEntityVelocity(event);
            
            // Modify velocity
            Vector3d velocity = packet.getVelocity();
            packet.setVelocity(new Vector3d(
                velocity.x * 1.5,
                velocity.y * 1.2,
                velocity.z * 1.5
            ));
        }
    }
}

Developer API Implementation

CRITICAL: Every plugin must include a complete, well-documented API for other plugins to integrate with.

API Interface (api/PluginNameAPI.java):

package com.example.plugin.api;

/**
 * Main API interface for PluginName
 * <p>
 * Access via: PluginName.getApi()
 * <p>
 * This API is guaranteed to be stable across minor versions.
 * Breaking changes will only occur in major version updates.
 * 
 * @since 1.0.0
 */
public interface PluginNameAPI {
    
    /**
     * Get the API version
     * @return API version string in format "major.minor.patch"
     */
    String getApiVersion();
    
    /**
     * Check if the plugin is fully loaded and ready to use
     * @return true if ready, false during startup/shutdown
     */
    boolean isReady();
    
    // Add your API methods here with full JavaDoc
    // Example:
    /**
     * Get player data for the specified player
     * @param uuid Player UUID
     * @return CompletableFuture containing player data, or null if not found
     */
    // CompletableFuture<PlayerData> getPlayerData(UUID uuid);
}

API Implementation (PluginNameAPIImpl.java, package-private):

package com.example.plugin;

import com.example.plugin.api.PluginNameAPI;

/**
 * Internal implementation of the API
 * <p>
 * Do not use this class directly - use PluginNameAPI interface instead
 */
class PluginNameAPIImpl implements PluginNameAPI {
    
    @Override
    public String getApiVersion() {
        return "1.0.0";
    }
    
    @Override
    public boolean isReady() {
        return PluginName.getInstance() != null && 
               PluginName.getInstance().isEnabled();
    }
    
    // Implement your API methods here
}

Custom Events (api/events/CustomEvent.java):

package com.example.plugin.api.events;

import lombok.Getter;
import lombok.Setter;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;

/**
 * Called when [describe when this event is called]
 * <p>
 * This event is cancellable. Cancelling it will prevent [action].
 * 
 * @since 1.0.0
 */
@Getter
public class CustomEvent extends Event implements Cancellable {
    
    private static final HandlerList HANDLERS = new HandlerList();
    
    private final Player player;
    // Add your event data fields
    
    @Setter
    private boolean cancelled;
    
    public CustomEvent(Player player) {
        super(true); // async if needed
        this.player = player;
    }
    
    @NotNull
    @Override
    public HandlerList getHandlers() {
        return HANDLERS;
    }
    
    @NotNull
    public static HandlerList getHandlerList() {
        return HANDLERS;
    }
}

Calling Custom Events:

// Fire your custom events
CustomEvent event = new CustomEvent(player);
Bukkit.getPluginManager().callEvent(event);

if (event.isCancelled()) {
    return; // Another plugin cancelled it
}
// Continue with action

Database Operations

Always async with CompletableFuture:

database.save("player:" + uuid, playerData)
    .thenAccept(success -> {
        if (success) {
            player.sendMessage("Data saved!");
        }
    });

Configuration Management

Type-safe with Lombok:

@Data
@Builder
public class PluginConfig {
    private boolean enabled;
    private String prefix;
    private DatabaseConfig database;
    private CombatConfig combat;
}

5. Quality Standards

Every plugin must include:

  1. Complete API System:

    • Public API interface (api/PluginNameAPI.java)
    • Package-private implementation
    • Custom events in api/events/
    • Full JavaDoc on all public methods
    • Example usage in README.md
  2. Professional Documentation:

    • README.md with features, installation, commands, API usage
    • CONTRIBUTING.md for contributors
    • CHANGELOG.md following Keep a Changelog format
    • CODE_OF_CONDUCT.md
    • Issue templates for bugs and features
  3. GitHub Actions CI/CD:

    • .github/workflows/build.yml for automated builds
    • .github/workflows/release.yml for automated releases
    • Dependabot for dependency updates
  4. Unit Tests:

    • JUnit 5 test structure
    • Test core functionality
    • Mock Bukkit/Paper API appropriately
  5. Code Quality:

    • Use zero deprecated APIs
    • Handle all operations asynchronously where appropriate
    • Include proper error handling and logging
    • Use concurrent collections for thread safety
    • Implement proper cleanup in onDisable()
    • Include configuration validation
    • Use Lombok to reduce boilerplate
    • Follow .editorconfig formatting
  6. Follow modern Java patterns (records, switch expressions where appropriate)

  7. Include proper plugin.yml with api-version

  8. Implement complete, working features (no placeholders)

6. Plugin.yml Template

name: PluginName
version: ${project.version}
main: com.example.pluginname.PluginName
api-version: '1.21'
author: YourName
description: Plugin description
website: https://example.com

# Load order
load: POSTWORLD
# or load: STARTUP for early loading

# Dependencies (optional)
depend: []
softdepend: []
loadbefore: []

# Commands (if any)
commands:
  commandname:
    description: Command description
    usage: /<command> [args]
    permission: pluginname.command
    aliases: [alias1, alias2]

# Permissions (optional)
permissions:
  pluginname.admin:
    description: Admin permission
    default: op
  pluginname.use:
    description: Basic usage permission
    default: true

Example Plugin Types

Combat Plugin

  • Custom knockback with PacketEvents
  • Hit detection and validation
  • Combat cooldowns
  • Damage modifiers
  • Anti-cheat integration

Economy Plugin

  • Database-backed player balances
  • Transaction system with async operations
  • Shop GUI with Adventure API
  • Multi-currency support
  • Transaction history

Game Mechanic Plugin

  • Custom entity behavior
  • Parkour systems with checkpoints
  • Mini-game framework
  • Event-driven mechanics
  • Async world manipulation

Anti-Cheat Plugin

  • Packet-based movement checks
  • Combat analysis (reach, killaura, etc.)
  • Speed and fly detection
  • Violation tracking and punishment
  • Analytics and logging

Performance Optimization

  1. Cache frequently accessed data

    private final Map<UUID, PlayerData> cache = new ConcurrentHashMap<>();
    
  2. Use async for I/O operations

    plugin.getServer().getAsyncScheduler().runNow(plugin, task -> {
        // Database or file operations
    });
    
  3. Minimize allocations in hot paths

    // Reuse objects, use primitive collections where appropriate
    
  4. Use packet manipulation instead of events when possible

    // PacketEvents is more performant than Bukkit events for certain tasks
    
  5. Batch database operations

    // Save multiple records in one transaction
    

Common Patterns

Manager Pattern

public class PlayerManager {
    private final Map<UUID, PlayerData> players = new ConcurrentHashMap<>();
    
    public CompletableFuture<PlayerData> loadPlayer(UUID uuid) {
        return database.load("player:" + uuid)
            .thenApply(opt -> {
                PlayerData data = opt.orElse(new PlayerData(uuid));
                players.put(uuid, data);
                return data;
            });
    }
    
    public CompletableFuture<Void> savePlayer(UUID uuid) {
        PlayerData data = players.get(uuid);
        if (data != null) {
            return database.save("player:" + uuid, data).thenAccept(success -> {});
        }
        return CompletableFuture.completedFuture(null);
    }
}

Command Pattern with Reflections

public abstract class BaseCommand implements CommandExecutor {
    protected final JavaPlugin plugin;
    
    public BaseCommand(JavaPlugin plugin) {
        this.plugin = plugin;
    }
}

// Auto-register all commands
Reflections reflections = new Reflections("com.example.pluginname.commands");
Set<Class<? extends BaseCommand>> commands = 
    reflections.getSubTypesOf(BaseCommand.class);

for (Class<? extends BaseCommand> cmdClass : commands) {
    BaseCommand cmd = cmdClass.getConstructor(JavaPlugin.class).newInstance(plugin);
    // Register command
}

Final Notes

  • Complete implementations only – No TODO comments or placeholder code
  • Test critical paths – Ensure database operations, packet handling work correctly
  • Modern Java features – Use records, pattern matching, text blocks where appropriate
  • Proper logging – Use plugin logger for important events
  • Clean code – Follow Java naming conventions, proper indentation
  • Documentation – Add Javadocs for public APIs and complex methods

Advanced Scenarios and Edge Cases

As an experienced developer, always consider and implement solutions for:

Concurrency and Thread Safety

Race Conditions:

  • Use ConcurrentHashMap for shared mutable state
  • Consider AtomicInteger, AtomicReference for counters/flags
  • Use synchronized blocks or ReentrantLock only when necessary
  • Prefer immutable objects (records, final fields)

Example:

// GOOD - Thread-safe counter
private final AtomicInteger activeGames = new AtomicInteger(0);

// GOOD - Immutable data transfer
public record PlayerStats(UUID uuid, int kills, int deaths, double kdr) {}

// CAREFUL - Synchronized block only for compound operations
private final Map<UUID, Integer> scores = new ConcurrentHashMap<>();
public void addScore(UUID player, int amount) {
    scores.merge(player, amount, Integer::sum); // Thread-safe
}

Memory Leaks Prevention

Common causes:

  1. Listeners not unregistered – Store listener instances, unregister in onDisable()
  2. Scheduled tasks not cancelled – Cancel all tasks in onDisable()
  3. Player data not cleaned up – Remove on PlayerQuitEvent
  4. Static collections – Clear in onDisable()
  5. Event handler references – Use WeakHashMap if caching players/entities

Example:

private final Set<BukkitTask> tasks = ConcurrentHashMap.newKeySet();

public void startTask(Runnable task) {
    BukkitTask scheduled = plugin.getServer().getScheduler()...;
    tasks.add(scheduled);
}

@Override
public void onDisable() {
    // Cancel all tasks
    tasks.forEach(BukkitTask::cancel);
    tasks.clear();
    
    // Clear player cache
    playerCache.clear();
    
    // Unregister listeners if dynamically registered
}

Database Transaction Safety

Handle failures gracefully:

public CompletableFuture<Boolean> transferMoney(UUID from, UUID to, double amount) {
    return CompletableFuture.supplyAsync(() -> {
        Connection conn = null;
        try {
            conn = dataSource.getConnection();
            conn.setAutoCommit(false); // Start transaction
            
            // Deduct from sender
            boolean deducted = deductBalance(conn, from, amount);
            if (!deducted) {
                conn.rollback();
                return false;
            }
            
            // Add to receiver
            boolean added = addBalance(conn, to, amount);
            if (!added) {
                conn.rollback();
                return false;
            }
            
            conn.commit(); // Commit transaction
            return true;
            
        } catch (SQLException e) {
            if (conn != null) {
                try {
                    conn.rollback();
                } catch (SQLException ex) {
                    plugin.getLogger().severe("Failed to rollback: " + ex.getMessage());
                }
            }
            plugin.getLogger().severe("Transaction failed: " + e.getMessage());
            return false;
        } finally {
            if (conn != null) {
                try {
                    conn.setAutoCommit(true);
                    conn.close();
                } catch (SQLException e) {
                    // Log but don't throw
                }
            }
        }
    });
}

Packet Event Edge Cases

Handle cancelled events:

@Override
public void onPacketReceive(PacketReceiveEvent event) {
    // Check if already cancelled by another listener
    if (event.isCancelled()) {
        return;
    }
    
    // Your logic here
    
    // Cancel with reason
    if (shouldCancel) {
        event.setCancelled(true);
        // Optionally notify player
        Player player = (Player) event.getPlayer();
        if (player != null) {
            player.sendMessage("Action blocked: " + reason);
        }
    }
}

Handle rapid packet spam:

private final Map<UUID, RateLimiter> packetLimiters = new ConcurrentHashMap<>();

@Override
public void onPacketReceive(PacketReceiveEvent event) {
    Player player = (Player) event.getPlayer();
    UUID uuid = player.getUniqueId();
    
    RateLimiter limiter = packetLimiters.computeIfAbsent(uuid, 
        k -> new RateLimiter(50, 1000)); // 50 packets per second
    
    if (!limiter.tryAcquire()) {
        event.setCancelled(true);
        plugin.getLogger().warning(player.getName() + " is sending packets too quickly!");
        return;
    }
    
    // Process packet normally
}

Configuration Migration

Handle config version changes:

public class ConfigMigration {
    private static final int CURRENT_VERSION = 3;
    
    public static void migrate(FileConfiguration config, JavaPlugin plugin) {
        int version = config.getInt("config-version", 1);
        
        if (version < CURRENT_VERSION) {
            plugin.getLogger().info("Migrating config from v" + version + " to v" + CURRENT_VERSION);
            
            if (version < 2) {
                migrateV1ToV2(config);
            }
            if (version < 3) {
                migrateV2ToV3(config);
            }
            
            config.set("config-version", CURRENT_VERSION);
            
            try {
                config.save(new File(plugin.getDataFolder(), "config.yml"));
            } catch (IOException e) {
                plugin.getLogger().severe("Failed to save migrated config: " + e.getMessage());
            }
        }
    }
    
    private static void migrateV1ToV2(FileConfiguration config) {
        // Rename old settings
        if (config.contains("old-setting")) {
            config.set("new-setting", config.get("old-setting"));
            config.set("old-setting", null);
        }
        
        // Add new default values
        config.addDefault("new-feature.enabled", true);
    }
}

Graceful Plugin Reload

Handle /reload command:

@Override
public void onDisable() {
    // Save all pending data SYNCHRONOUSLY
    saveAllData().join(); // Wait for completion
    
    // Cancel tasks
    cancelAllTasks();
    
    // Close connections
    closeConnections();
    
    getLogger().info("Plugin disabled safely");
}

@Override
public void onEnable() {
    // Check if this is a reload
    if (isReloading()) {
        getLogger().warning("Plugin reloaded. Some features may not work correctly. Restart recommended.");
    }
    
    // Re-initialize everything
}

private boolean isReloading() {
    // Check if players are online (would be 0 on first server start)
    return !Bukkit.getOnlinePlayers().isEmpty();
}

API Version Compatibility

Handle different Paper versions:

public class VersionAdapter {
    private static final String VERSION;
    
    static {
        String packageName = Bukkit.getServer().getClass().getPackage().getName();
        VERSION = packageName.substring(packageName.lastIndexOf('.') + 1);
    }
    
    public static boolean isModernVersion() {
        // 1.20.5+ has different packet structure
        return VERSION.compareTo("v1_20_R4") >= 0;
    }
    
    public static void sendActionBar(Player player, String message) {
        if (isModernVersion()) {
            player.sendActionBar(Component.text(message));
        } else {
            // Legacy method
            player.spigot().sendMessage(ChatMessageType.ACTION_BAR, 
                TextComponent.fromLegacyText(message));
        }
    }
}

Error Recovery Patterns

Implement circuit breaker for external services:

public class CircuitBreaker {
    private final int threshold;
    private final long timeout;
    private AtomicInteger failures = new AtomicInteger(0);
    private volatile long lastFailureTime = 0;
    private volatile boolean open = false;
    
    public boolean isOpen() {
        if (open && System.currentTimeMillis() - lastFailureTime > timeout) {
            open = false; // Try again after timeout
            failures.set(0);
        }
        return open;
    }
    
    public void recordSuccess() {
        failures.set(0);
        open = false;
    }
    
    public void recordFailure() {
        lastFailureTime = System.currentTimeMillis();
        if (failures.incrementAndGet() >= threshold) {
            open = true;
        }
    }
}

// Usage in database operations
public CompletableFuture<Boolean> save(String key, Object value) {
    if (circuitBreaker.isOpen()) {
        plugin.getLogger().warning("Circuit breaker open, skipping database operation");
        return CompletableFuture.completedFuture(false);
    }
    
    return CompletableFuture.supplyAsync(() -> {
        try {
            // Database operation
            circuitBreaker.recordSuccess();
            return true;
        } catch (Exception e) {
            circuitBreaker.recordFailure();
            plugin.getLogger().severe("Database operation failed: " + e.getMessage());
            return false;
        }
    });
}

Performance Monitoring

Add built-in performance metrics:

public class PerformanceMonitor {
    private final Map<String, LongAdder> operationCounts = new ConcurrentHashMap<>();
    private final Map<String, LongAdder> operationTimes = new ConcurrentHashMap<>();
    
    public void recordOperation(String operation, long durationNanos) {
        operationCounts.computeIfAbsent(operation, k -> new LongAdder()).increment();
        operationTimes.computeIfAbsent(operation, k -> new LongAdder())
            .add(durationNanos);
    }
    
    public void printStats() {
        plugin.getLogger().info("=== Performance Stats ===");
        operationCounts.forEach((op, count) -> {
            long totalTime = operationTimes.get(op).sum();
            long avgTime = totalTime / count.sum();
            plugin.getLogger().info(String.format("%s: %d calls, avg %d μs",
                op, count.sum(), avgTime / 1000));
        });
    }
}

// Usage
long start = System.nanoTime();
try {
    // Your operation
} finally {
    performanceMonitor.recordOperation("database.save", System.nanoTime() - start);
}

These advanced patterns should be implemented where appropriate based on the plugin’s complexity and requirements.

Documentation and Project Delivery

CRITICAL: Complete Project Checklist

When delivering a plugin, ALWAYS generate ALL of these files:

1. Source Code Files

  • ✅ All Java source files in proper package structure
  • ✅ Complete API package with interfaces and events
  • ✅ Unit tests in src/test/
  • ✅ plugin.yml with all metadata
  • ✅ config.yml with all configuration options
  • ✅ messages.yml (if using messages)

2. Build Configuration

  • ✅ pom.xml or build.gradle.kts with all dependencies
  • ✅ Maven wrapper files (mvnw, mvnw.cmd) or Gradle wrapper

3. Documentation Files

  • ✅ README.md – Complete project documentation with:
    • Project description and features
    • Installation instructions
    • Configuration guide
    • Commands and permissions tables
    • API usage examples
    • Links to wiki/Discord/issues
    • Badges (build status, license, version)
  • ✅ CHANGELOG.md – Version history following Keep a Changelog
  • ✅ CONTRIBUTING.md – How to contribute
  • ✅ CODE_OF_CONDUCT.md – Community guidelines
  • ✅ LICENSE – MIT License (or as specified)

4. GitHub Configuration

  • ✅ .github/workflows/build.yml – CI/CD build pipeline
  • ✅ .github/workflows/release.yml – Automated releases
  • ✅ .github/ISSUE_TEMPLATE/bug_report.md – Bug report template
  • ✅ .github/ISSUE_TEMPLATE/feature_request.md – Feature request template
  • ✅ .github/dependabot.yml – Dependency updates

5. Code Quality Files

  • ✅ .editorconfig – Code formatting rules
  • ✅ .gitignore – Git ignore rules

README.md Generation Guidelines

ALWAYS customize the README.md with:

  1. Replace all placeholders:

    • PluginName → actual plugin name
    • username → GitHub username
    • [Feature descriptions] → actual features
    • Example commands → actual commands from plugin
    • Example permissions → actual permissions
    • Discord/support links → real links or remove
  2. Add accurate feature list based on what the plugin actually does

  3. Include complete command/permission tables with all commands implemented

  4. Write API usage examples using the actual API methods created

  5. Add relevant badges:

    [![Build Status](https://github.com/username/plugin-name/workflows/Build/badge.svg)](https://github.com/username/plugin-name/actions)
    [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
    [![Paper](https://img.shields.io/badge/Paper-1.21.3-blue.svg)](https://papermc.io/)
    
  6. Include configuration example from the actual config.yml

CHANGELOG.md Initialization

Start with:

# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added
- Initial plugin features

## [1.0.0] - YYYY-MM-DD

### Added
- [List all initial features]
- Complete developer API
- Database support (SQLite/MySQL/PostgreSQL)
- Configuration system
- [Specific feature 1]
- [Specific feature 2]

[Unreleased]: https://github.com/username/plugin-name/compare/v1.0.0...HEAD
[1.0.0]: https://github.com/username/plugin-name/releases/tag/v1.0.0

Unit Test Example

Always include at least one test:

package com.example.plugin;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.BeforeEach;
import static org.junit.jupiter.api.Assertions.*;

class PluginNameTest {
    
    @BeforeEach
    void setUp() {
        // Setup mocks if needed
    }
    
    @Test
    void testApiVersion() {
        // Example test - adapt to your plugin
        assertEquals("1.0.0", "1.0.0");
    }
    
    @Test
    void testConfigValidation() {
        // Test configuration validation
        assertTrue(true);
    }
}

File Organization

Organize generated files in the output directory:

/mnt/user-data/outputs/PluginName/
├── src/
│   ├── main/
│   │   ├── java/...
│   │   └── resources/...
│   └── test/...
├── .github/...
├── README.md
├── CHANGELOG.md
├── CONTRIBUTING.md
├── CODE_OF_CONDUCT.md
├── LICENSE
├── pom.xml
├── .editorconfig
├── .gitignore
└── mvnw / mvnw.cmd

Presentation to User

After generating all files, present them with:

I've created a complete, production-ready [PluginName] plugin with:

✅ Full source code with API system
✅ Complete documentation (README, CHANGELOG, CONTRIBUTING)
✅ GitHub Actions CI/CD
✅ Unit test structure
✅ Issue templates and code of conduct

The plugin includes:
- [Feature 1]
- [Feature 2]
- Complete developer API for integrations
- [Database type] database support
- Async operations throughout

To use:
1. Build: `mvn clean package`
2. Find JAR in `target/` directory
3. Place in your server's `plugins/` folder

For development:
- API usage examples in README.md
- Extend the API by adding methods to PluginNameAPI interface
- Add custom events in `api/events/` package

All files are ready for GitHub - just create a repository and push!

Reference Templates

For complete file templates, ALWAYS refer to references/professional-template.md which contains:

  • Complete README.md template
  • GitHub Actions workflows
  • Issue templates
  • All documentation files
  • API structure examples

This ensures consistent, professional output for every plugin!