Architecture Overview
This document describes the system architecture of Pilaf, a YAML story-driven testing framework for Minecraft plugins.
System Overview
Pilaf follows a layered architecture with clear separation of concerns:
┌─────────────────────────────────────────────────────────────────────┐
│ Pilaf TEST FRAMEWORK │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ TEST LAYER (YAML Stories) │ │
│ │ ┌──────────────────────┐ ┌──────────────────────┐ │ │
│ │ │ Story Files │ │ Configuration Files │ │ │
│ │ │ • test-*.yaml │ │ • pilaf.yaml │ │ │
│ │ │ • *.yaml │ │ • config-*.yaml │ │ │
│ │ └──────────┬───────────┘ └──────────┬───────────┘ │ │
│ └─────────────┼─────────────────────────┼───────────────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ ORCHESTRATION LAYER │ │
│ │ ┌──────────────────────┐ ┌──────────────────────┐ │ │
│ │ │ TestOrchestrator │ │ YamlStoryParser │ │ │
│ │ │ (Timeline Replay) │ │ (YAML DSL Parser) │ │ │
│ │ │ • Story execution │ │ • Parse YAML stories │ │ │
│ │ │ • Action sequencing │ │ • Create Action objs │ │ │
│ │ │ • Result aggregation │ │ • Validation │ │ │
│ │ └──────────┬───────────┘ └──────────┬───────────┘ │ │
│ └─────────────┼─────────────────────────┼───────────────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ BACKEND LAYER │ │
│ │ ┌──────────────┐ ┌──────────────┐ ┌────────────────────┐ │ │
│ │ │ PilafBackend │◀─┤ Backend │ │ PilafBackendFactory│ │ │
│ │ │ (Interface) │ │ Factory │ │ (creates backends) │ │ │
│ │ │ • Player ops │ │ • Config mgmt│ │ • Backend selection│ │ │
│ │ │ • Entity ops │ │ • Creation │ │ • Initialization │ │ │
│ │ │ • Server cmds│ │ • Validation │ │ • Dependency inject │ │ │
│ │ └──────┬───────┘ └──────────────┘ └────────────────────┘ │ │
│ │ │ │ │
│ │ ├─────────────────┬─────────────────┬────────────────┐ │ │
│ │ ▼ ▼ ▼ │ │ │
│ │ ┌──────────────┐ ┌──────────────┐ ┌────────────────────┐ │ │ │
│ │ │ Mineflayer │ │ HeadlessMc │ │ Docker/RCON │ │ │ │
│ │ │ Backend │ │ Backend │ │ Backend │ │ │ │
│ │ │ • Player sim │ │ • Self-cont. │ │ • Server commands │ │ │ │
│ │ │ • HTTP API │ │ • CI/CD opt │ │ • RCON protocol │ │ │ │
│ │ │ • Bridge │ │ • Auto-launch│ │ • Full server acc │ │ │ │
│ │ └──────┬───────┘ └──────┬───────┘ └──────────┬───────────┘ │ │ │
│ └───────────────────────────┼─────────────────────┼───────────────┘ │ │
│ │ │ │ │
└──────────────────────────────┼─────────────────────┼──────────────────┘
│ │
▼ ▼
┌──────────────────────────────────────────────────────────────────────┐
│ COMMUNICATION LAYER │
│ │
│ ┌───────────────────────┐ ┌──────────────────────────────┐ │
│ │ RconClient │ │ MineflayerBridge (Node.js) │ │
│ │ (Java, TCP) │ │ HTTP/WebSocket Server │ │
│ │ Port: 25575 │ │ Port: 3000 │ │
│ └───────────┬───────────┘ └───────────┬──────────────────┘ │
│ │ │ │
│ │ │ │
│ │ ▼ │
│ │ ┌──────────────────────────────┐ │
│ │ │ PilafMineflayerClient │ │
│ │ │ (Java HTTP Client) │ │
│ │ │ • REST API calls │ │
│ │ │ • JSON responses │ │
│ │ └───────────────┬──────────────┘ │
│ │ │ │
└──────────────┼──────────────────────────────────┼────────────────────┘
│ │
▼ ▼
┌──────────────────────────────────────────────────────────────────────┐
│ MINECRAFT SERVER LAYER │
│ │
│ ┌────────────────────────────────────────────────────────────────┐ │
│ │ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────┐ │ │
│ │ │ PaperMC Server │ │ RCON Interface │ │ Minecraft │ │ │
│ │ │ (Docker/Local) │ │ Port: 25575 │ │ Game Port: │ │ │
│ │ │ • Version 1.20.4+│ │ • Command exec │ │ 25565 │ │ │
│ │ │ • Plugins │ │ • Query support │ │ • Multiplayer│ │ │
│ │ │ • World data │ │ • Auth required │ │ • Player act │ │ │
│ │ └──────────────────┘ └──────────────────┘ └──────────────┘ │ │
│ │ │ │
│ └──────────────────────────────────────────────────────────────────┘ │
│ │
└───────────────────────────────────────────────────────────────────────┘
Source Code Structure
Main Application Layer
src/main/java/org/cavarest/pilaf/
├── cli/ # Command Line Interface
│ ├── PilafCli.java # Main CLI entry point
│ ├── ConfigLoader.java # Configuration file loader
│ └── StoryDiscoverer.java # Story file discovery
├── orchestrator/ # Test Orchestration
│ ├── TestOrchestrator.java # Main orchestration logic
│ └── StoryExecutor.java # Story execution engine
├── parser/ # YAML Parsing
│ └── YamlStoryParser.java # YAML story parser
├── backend/ # Backend Abstraction
│ ├── PilafBackend.java # Backend interface
│ ├── PilafBackendFactory.java # Backend factory
│ ├── MineflayerBackend.java # Mineflayer implementation
│ ├── HeadlessMcBackend.java # HeadlessMc implementation
│ ├── DockerServerBackend.java # Docker backend
│ └── RconBackend.java # RCON backend
├── config/ # Configuration Management
│ ├── TestConfiguration.java # Configuration model
│ └── ConnectionManager.java # Connection handling
├── model/ # Data Models
│ ├── Action.java # Action model
│ ├── Assertion.java # Assertion model
│ ├── TestStory.java # Story model
│ └── TestResult.java # Result model
├── report/ # Reporting
│ ├── TestReporter.java # Main reporter
│ └── HtmlReportGenerator.java # HTML report generation
├── rcon/ # RCON Protocol
│ └── RconClient.java # RCON protocol implementation
├── client/ # Client Communication
│ └── MineflayerClient.java # Mineflayer HTTP client
└── testing/ # Testing Framework
└── BackendConsistencyTester.java
Backend Implementations
Docker Backend
The Docker backend launches a PaperMC server in a Docker container and communicates via RCON.
-
Container Image:
itzg/minecraft-server:java21 -
RCON Port: 25575
-
Minecraft Port: 25565
-
Network: Custom bridge network (172.20.0.0/16)
backend:
type: docker
docker:
server_image: "itzg/minecraft-server:java21"
network_name: "pilaf-network"
Mineflayer Backend
The Mineflayer backend uses a Node.js bridge server to control a headless Minecraft client.
-
Runtime: Node.js 16+
-
Framework: Express.js
-
Library: Mineflayer v4.33.0
-
Communication: HTTP/REST API on port 3000
backend:
type: mineflayer
client:
host: "localhost"
port: 3000
HeadlessMc Backend
The HeadlessMc backend is a self-contained Java implementation for CI/CD environments.
-
Runtime: Java 21
-
Server Management: Self-contained PaperMC launcher
-
RCON: Fallback mechanism for server commands
-
CI/CD: Optimized for GitHub Actions
backend:
type: headlessmc
server:
minecraft_version: "1.20.4"
Key Design Patterns
1. Backend Abstraction Pattern
Pilaf uses an interface-based backend system with factory pattern:
public interface PilafBackend {
void initialize() throws Exception;
void cleanup() throws Exception;
String getType();
// Core action methods...
}
public class PilafBackendFactory {
public static PilafBackend create(String type, String... args) {
switch (type.toLowerCase()) {
case "mineflayer": return new MineflayerBackend(...);
case "headlessmc": return new HeadlessMcBackend(...);
case "docker": return new DockerServerBackend(...);
default: throw new IllegalArgumentException("Unknown backend: " + type);
}
}
}
2. YAML Story DSL Design
Pilaf uses a declarative YAML format with structured action definitions:
name: "Test Story"
setup:
- action: "execute_rcon_command"
command: "op test_player"
steps:
- action: "give_item"
player: "test_player"
item: "diamond_sword"
count: 1
cleanup:
- action: "execute_rcon_command"
command: "deop test_player"
Data Flow
-
Story Loading: YAML → Parser → Action objects
-
Action Execution: Orchestrator → Backend → Communication → Server
-
State Management: Actions → Variables → Storage → Retrieval
-
Result Aggregation: Actions → Results → Reporter → Output
State Management
Pilaf provides centralized state management with variable storage:
public class TestOrchestrator {
private Map<String, Object> storedStates = new HashMap<>();
public void storeState(String variableName, Object value) {
storedStates.put(variableName, value);
}
public Object getState(String variableName) {
return storedStates.get(variableName);
}
}
This enables complex test scenarios with state comparison and dynamic test flow based on runtime state.
Error Handling Strategy
-
Graceful Degradation: Fallback mechanisms for backend limitations
-
Comprehensive Logging: Detailed logs for debugging and analysis
-
Health Monitoring: Service availability checking and reporting
Next Steps
-
Writing Stories - Learn the YAML DSL
-
Command Reference - Complete action reference
-
Troubleshooting - Common issues and solutions