DistroCraft
Distributed computing for Minecraft — let your players contribute their idle CPU cycles to power your server.
Downloads
Get DistroCraft
Select your platform and version to download the right build.
Documentation
What is DistroCraft?
DistroCraft splits CPU-bound work into small tasks and dispatches them to connected player machines. Results are returned asynchronously to the server. Communication uses Minecraft's custom payload system — no extra ports needed for the mod variant.
Components
Server Mod
NeoForge + Fabric 1.21.x server-side mod. Drops into mods/.
Client Mod
NeoForge + Fabric 1.21.x client mod. Drops into .minecraft/mods/.
Standalone App
Pure Java app (GUI + CLI). No Minecraft required. Connect from anywhere.
Paper Plugin
Paper 1.21.x server plugin. Alternative to the server mod — uses TCP port.
Use either the server mod or the Paper plugin — not both. Players use either the client mod or the standalone app.
License
DistroCraft is licensed under GNU GPLv3.
1. Server (mod or plugin)
NeoForge / Fabric mod: Drop the server mod JAR into your server's mods/ folder. The coordinator starts automatically.
Paper plugin: Drop the plugin JAR into plugins/. Configure via plugins/DistrocraftServer/config.yml.
2. Players (mod)
Drop the client mod JAR into .minecraft/mods/. Use /distro start to connect — you'll automatically contribute your spare CPU cycles.
3. Players (standalone app)
GUI mode: java -jar DistroCraft-app-*.jar
CLI mode: java -jar DistroCraft-app-*.jar <host> [port] [threads] [label]
java -jar DistroCraft-app-1.0.0.jar play.myserver.com 25566 4 Steve
Requirements
Java 21 or later. For mods: Minecraft 1.21.x with NeoForge 21.1+ or Fabric Loader 0.16+.
Player In-Game Commands
Type these in chat (prefixed with /distro):
| Command | Description |
|---|---|
| /distro start | Connect to the server's coordinator |
| /distro stop | Disconnect from the coordinator |
| /distro status | Show connection status and task stats |
| /distro set threads <n> | Set worker thread count |
| /distro set resources <key>=<value> ... | Set resource limits (e.g. ram_mb=2048) |
Server Plugin Commands
| Command | Description |
|---|---|
| /dc status | Overall coordinator stats |
| /dc list | List connected clients with capabilities |
| /dc submit <KIND> <k>=<v> ... | Queue a task of any kind |
Server Mod config/distrocraft-server.properties
port=25566 enabled=true requireInGame=true maxClientsPerPlayer=1 debugLogging=false taskTimeoutSec=60 clientTimeoutSec=30
Player Mod .minecraft/config/distrocraft-client.properties
host=localhost port=25566 threads=2 autoStart=false showHud=true # Additional resources: resource.ram_mb=2048
Paper Plugin plugins/DistrocraftServer/config.yml
YAML config with the same options as the server mod. Created automatically on first run.
Wire Format
All communication is newline-delimited JSON over custom payload packets (mods) or TCP (app/plugin).
SERVER → CLIENT HELLO {"type":"HELLO","version":1,"serverId":"<uuid>"}
CLIENT → SERVER REGISTER {"type":"REGISTER","clientId":"...","maxThreads":4,"playerName":"Steve","capabilities":{"threads":4,"ram_mb":2048}}
SERVER → CLIENT TASK {"type":"TASK","taskId":"<uuid>","kind":"CHUNK_GEN","payload":{...}}
CLIENT → SERVER RESULT {"type":"RESULT","taskId":"...","success":true,"data":{...}}
EITHER PING/PONG {"type":"PING"} / {"type":"PONG"}
SERVER → CLIENT DISCONNECT {"type":"DISCONNECT","reason":"..."}
Dynamic Task Kinds
Task kinds are arbitrary strings — there is no enum. Any string is a valid task kind. Register handlers on both sides.
Built-in Examples
| Kind | Payload | Result |
|---|---|---|
| CHUNK_GEN | cx, cz, dimension, seed | cx, cz, heightmap |
| PATHFIND | x1,y1,z1, x2,y2,z2, context | found, estimatedLength, pathJson |
| STRUCTURE_SCAN | x1,z1, x2,z2, seed, structureId | candidateX, candidateZ, confidence |
| PHYSICS_SIM | simulationType, params | simulationType, stepsCompleted, energy |
| CUSTOM | any JsonObject | echo + processed:true |
Custom Task Handler Example
// Register on the client:
TaskExecutor.getRegistry().register("AERONAUTICS_PHYSICS", payload -> {
JsonObject result = new JsonObject();
// your solver here
return result;
});
// Submit from the server:
DistroTask task = DistroTask.of("AERONAUTICS_PHYSICS", payload);
coordinator.submitTask(task);