FrameworkPlugin is a production-grade, modular plugin framework for Minecraft Paper servers. It follows Clean Architecture principles with strict separation of concerns.
┌─────────────────────────────────────────┐
│ Presentation Layer │
│ (Commands, Events, GUI) │
├─────────────────────────────────────────┤
│ Application Layer │
│ (Use Cases, Business Logic) │
├─────────────────────────────────────────┤
│ Domain Layer (API) │
│ (Interfaces, Entities, Value Objects) │
├─────────────────────────────────────────┤
│ Infrastructure Layer (Core) │
│ (Implementations, External Services) │
└─────────────────────────────────────────┘
Location: core/di/Container.java
Purpose: Lightweight DI container for service management
Features:
- Singleton registration
- Factory registration
- Thread-safe (double-checked locking)
- Type-safe resolution
Usage:
Container container = Container.getInstance();
container.registerSingleton(EventBus.class, new EventBusImpl());
EventBus eventBus = container.resolve(EventBus.class).orElseThrow();Location: api/module/, core/module/
Purpose: Dynamic module loading with dependency resolution
Features:
- Topological sorting for load order
- Dependency validation
- Hot reload support
- Lifecycle management (load → enable → disable → unload)
Module Lifecycle:
┌──────┐ ┌────────┐ ┌─────────┐ ┌──────────┐
│ Load │ -> │ Enable │ -> │ Running │ -> │ Disable │
└──────┘ └────────┘ └─────────┘ └──────────┘
↓ ↓
┌────────┐ ┌────────┐
│ Reload │ │ Unload │
└────────┘ └────────┘
Location: api/event/, core/event/
Purpose: Custom event system for cross-module communication
Features:
- Priority-based event handling
- Cancellable events
- Async event posting
- Type-safe subscriptions
Event Flow:
Publisher -> EventBus -> [Priority Queue] -> Subscribers
↓
[LOWEST → LOW → NORMAL → HIGH → HIGHEST → MONITOR]
Location: api/script/, core/script/
Purpose: Sandboxed JavaScript execution using GraalVM
Features:
- ECMAScript 2022 support
- Sandboxing (no file I/O, restricted class access)
- Hot reload
- Error isolation
- Execution tracking
Security Model:
JavaScript Code
↓
Sandbox Layer (GraalVM Context)
↓
API Layer (ScriptAPIImpl)
↓
Plugin Services
Location: api/item/, core/item/
Purpose: Custom items with abilities and NBT data
Features:
- Immutable item definitions
- Ability system with cooldowns
- NBT persistence
- Rarity system
- Builder pattern for creation
Item Structure:
CustomItem
├── ID (unique identifier)
├── Material (base Bukkit material)
├── Display Name
├── Lore
├── Custom Model Data
├── NBT Data (key-value pairs)
├── Abilities (list of ItemAbility)
├── Rarity (COMMON → MYTHIC)
└── Unbreakable flag
Location: api/scheduler/, core/scheduler/
Purpose: Wrapper around BukkitScheduler with better API
Features:
- CompletableFuture support
- TimeUnit-based delays
- Task tracking
- Owner-based cancellation
- Where: Throughout the framework
- Why: Loose coupling, testability, flexibility
- Where: Storage layer
- Why: Abstract data access, swappable backends
- Where: Event bus
- Why: Decoupled communication
- Where: Storage providers
- Why: Pluggable storage backends
- Where: Item creation, GUI building
- Why: Fluent API, immutability
- Where: Module creation
- Why: Encapsulate object creation
- Where: DI container, managers
- Why: Single instance, global access (thread-safe)
- Immutable Objects: All API entities are immutable (records)
- Concurrent Collections: ConcurrentHashMap for all registries
- Atomic Operations: AtomicBoolean, AtomicInteger for state
- CompletableFuture: All async operations return futures
- No Shared Mutable State: Each module has isolated state
Main Thread (Bukkit)
├── Event Handling
├── Command Execution
└── Synchronous Tasks
Async Thread Pool
├── Module Loading
├── Script Execution
├── Storage Operations
└── Heavy Computations
- Modules load on-demand
- Configs load when first accessed
- Scripts compile once, execute many times
- Module descriptors cached
- Item definitions cached
- Script contexts reused
- Storage batch saves
- Event batch processing
- Cooldown cleanup batching
- All file operations async
- Database operations async
- Network operations async
- Reuse expensive objects
- Minimize allocations
- Reduce GC pressure
- Fail Fast: Validate early, throw exceptions
- Graceful Degradation: Continue on non-critical errors
- Error Isolation: Module errors don't crash plugin
- Detailed Logging: All errors logged with context
- Recovery: Auto-recovery where possible
Error Occurs
↓
Log Error (with context)
↓
Notify Affected Components
↓
Attempt Recovery
↓
If Recovery Fails → Disable Component
↓
Continue Plugin Operation
Implement Module interface or extend BaseModule
Implement StorageProvider interface
Implement ItemAbility interface
Implement PluginEvent interface
Add methods to ScriptAPIImpl
- Test individual components in isolation
- Mock dependencies
- Fast execution
- Test component interactions
- Use test containers
- Realistic scenarios
- Load testing
- Stress testing
- Memory profiling
mvn clean package
→ Copy to test server
→ Reload plugin
→ Test changes
mvn clean package -P production
→ Run tests
→ Security scan
→ Deploy to server
→ Monitor logs
- Module load times
- Script execution times
- Event processing times
- Memory usage
- Active tasks count
- Error rates
- SEVERE: Critical errors
- WARNING: Non-critical issues
- INFO: Important events
- FINE: Debug information
- FINER: Detailed debug
- FINEST: Trace level
- Web Dashboard: Real-time monitoring and control
- Database Integration: MySQL, PostgreSQL support
- Metrics System: Prometheus integration
- Hot Code Reload: Reload Java code without restart
- Distributed Modules: Load modules from remote sources
- API Gateway: REST API for external integrations
- Plugin Marketplace: Download modules from repository
- Use DI Container: Don't create services manually
- Async Operations: Use CompletableFuture for I/O
- Error Handling: Catch and log all exceptions
- Resource Cleanup: Unregister everything in onDisable
- Thread Safety: Use concurrent collections
- Documentation: Document all public APIs
- Keep Scripts Small: One responsibility per script
- Error Handling: Use try-catch in scripts
- Avoid Blocking: Don't block the main thread
- Use API: Don't access Bukkit directly
- Test Thoroughly: Test scripts before deployment
-
Module Won't Load
- Check dependencies in module.yml
- Verify module.yml syntax
- Check logs for errors
-
Script Errors
- Check script syntax
- Verify API usage
- Enable debug logging
-
Performance Issues
- Profile with JProfiler
- Check for memory leaks
- Review async operations
-
Thread Deadlocks
- Use thread dumps
- Review synchronization
- Check for circular waits