Prismarine Viewer
👁️ Prismarine Viewer#
Browser-based 3D visualization of Mineflayer bots using Three.js + WebGL.
Quick Start#
const { mineflayer: mineflayerViewer } = require('prismarine-viewer')
bot.once('spawn', () => {
mineflayerViewer(bot, { port: 3007, firstPerson: true })
})
Configuration#
| Option | Type | Default | Description |
|---|---|---|---|
port |
number | 3000 |
Web server port |
firstPerson |
boolean | false |
true = bot’s eyes, false = free cam |
viewDistance |
number | 6 |
Render distance in chunks |
prefix |
string | '' |
URL prefix (e.g., /viewer) |
Moincraft Wiring#
- Global viewer:
bots/viewer.js→ port55669 - Per-agent POV: Extra Prismarine instance on
agent.viewerPort(directhostname:port) - Dashboard iframe:
Viewer.svelteswitches between global feed and per-agent feeds - Proxy mode: Set
VITE_USE_VIEWER_PROXY(default) → uses/viewer/path (same origin, avoids mixed content) - Direct mode:
http(s)://<current-host>:<port>viagetDirectViewerUrl()
Controls#
- W/A/S/D: Move camera (third person)
- Space/Shift: Up/down
- Mouse drag: Look around
- Click: Interact (if enabled)
Version Compatibility Layer#
Server runs 1.21.11 but prismarine-viewer supports up to 1.21.4:
Proxy(bot) → version: "1.21.4" (renderVersion)
→ world.getColumnAt() → column.toJson() → remapChunkJsonPalette()
palette stateIds: 1.21.11 space → 1.21.4 space
→ bot.on('blockUpdate') → remapped stateId
Env overrides: VIEWER_RENDER_VERSION, VIEWER_VERSION_FALLBACK=false
Performance Tuning#
The Golden Rule: View Distance#
| Setting | Loaded Chunks | Recommendation |
|---|---|---|
| 6 (default) | ~169 chunks | Too heavy for swarm |
| 3 | ~49 chunks | Sweet spot — 75% reduction |
CPU Relief#
mineflayerViewer(bot, {
port: 3000,
firstPerson: true,
viewDistance: 3, // ← key setting
})
Air Chunk Bottleneck#
- Symptom: Bot freezes 10-30s on start
- Cause: Prismarine generates empty “air” chunks on main thread
- Fix: Wait for viewer to stabilize before complex movements
Browser-Side#
- Reduce window size (fewer pixels)
- Enable hardware acceleration in Chrome/Edge
- Refresh page periodically (memory leak mitigation)
Entity Tracking#
Lower entity-tracking-range in spigot.yml to reduce WebSocket spam to the viewer.
Headless Vision (LLM Screenshots)#
const browser = await puppeteer.launch({
headless: "new",
args: ['--no-sandbox', '--disable-setuid-sandbox'] // Linux/Docker essential
});
Tips:
- Pause rendering when bot isn’t looking
- 640×480 is enough for LLM to “see” — don’t screenshot at 4K
- Use dedicated “Spectator” bot to avoid impacting agent logic
Embedding in Dashboard#
<iframe src="http://localhost:3007" width="100%" height="500px" frameborder="0"></iframe>
Blank iframe troubleshooting:
- Dashboard HTTPS + per-agent HTTP = mixed content blocked → use proxy
- Bot hasn’t spawned / received chunks → wait for spawn event
- Port not open → check firewall
Reconnect Strategy#
Exponential backoff: min(base × 2^attempts, max) + random(jitter)
| Setting | Default |
|---|---|
VIEWER_RECONNECT_BASE_MS |
5000 |
VIEWER_RECONNECT_MAX_MS |
60000 |
VIEWER_RECONNECT_JITTER_MS |
1500 |
VIEWER_RECONNECT_DUPLICATE_MS |
30000 |
Duplicate login: fixed 30s wait. Version mismatch kick: auto-fallback to version: auto.