Specimen Report
· Elixir
mc-fun
phiat/mc-fun
Minecraft server dashboard in Elixir/Phoenix — RCON console, mineflayer bot fleet, LLM-powered chat, real-time events
- Stars
- ★ 1
- Forks
- ⑂ 0
- Language
- Elixir
- Size
- 688 kB
- Last Push
- 2mo ago
- Forged
- 3mo ago
dashboardelixirllmminecraftmineflayerphoenixrcon
# MC Fun
Phoenix LiveView control panel for a Minecraft server. Manage bots, execute RCON commands, fire effects, render block text, and watch events — all from a browser dashboard or the command line.

## Features
**Bots**
- Spawn and control [mineflayer](https://github.com/PrismarineJS/mineflayer) bots via Erlang Ports
- LLM chat via Groq — bots respond to players, perform actions based on LLM output
- A* pathfinding (mineflayer-pathfinder) for goto, follow, patrol
- 22 personality presets across 6 categories
- Behaviors: patrol (waypoint loop), follow (player), guard (position + radius), mine (block type)
- Job queue for sequential actions (go to X → mine Y → return to Z)
- Per-bot config modal: model, personality, behaviors, actions
**Dashboard**
- Live bot cards with HP/food bars, position, dimension, activity state, job queue
- Player cards with stats and `[USE]` coord buttons
- RCON terminal with command history, Tab-repeat, and quick command palette
- Entity picker dropdowns in FX and Display panels
- Effects panel with presets + custom title/subtitle messages
- Block text display with entity-based coordinate fill
- Real-time event stream (joins, leaves, chat, deaths, advancements)
**CLI**
- Full suite of `mix mc.*` tasks mirroring dashboard functionality
- Effects, titles, sounds, and particles via `mix mc.fx`
- Live event watcher and system health check
**Engine**
- SNBT parser — recursive descent parser for Minecraft's NBT text format
- In-memory state (GenServers, ETS, EventStore) — no database
## Setup
### 1. Infrastructure (Incus containers)
Requires [Incus](https://linuxcontainers.org/incus/) installed on the host.
```bash
bin/mc up # launch Minecraft + Postgres containers
bin/mc status # show IPs and connection strings
bin/mc doctor # verify everything is healthy
```
### 2. Elixir app (runs on host)
```bash
cp .env.example .env # fill in IPs from `bin/mc status`
mix deps.get
cd apps/mc_fun/priv/mineflayer && npm install && cd ../../../..
mix phx.server # http://localhost:4000/dashboard
```
### Infrastructure CLI (`bin/mc`)
```bash
bin/mc up [mc|pg|all] # start containers (default: all)
bin/mc down # stop all containers
bin/mc status # show containers, IPs, connection strings
bin/mc connect mc # shell into Minecraft container
bin/mc connect pg # psql into Postgres
bin/mc logs mc 100 # last 100 lines of MC server logs
bin/mc doctor # health check
```
### Ports
| Service | Port | Protocol |
|------------|-------|----------|
| Minecraft | 25565 | TCP |
| RCON | 25575 | TCP |
| Postgres | 5432 | TCP |
| Phoenix | 4000 | HTTP |
### Environment Variables
| Variable | Description |
|----------|-------------|
| `RCON_HOST` | Minecraft container IP (from `bin/mc status`) |
| `RCON_PORT` | RCON port (default: 25575) |
| `RCON_PASSWORD` | RCON password (default: mc-fun-rcon) |
| `MC_HOST` | Minecraft container IP (same as RCON_HOST) |
| `MC_PORT` | Minecraft server port (default: 25565) |
| `GROQ_API_KEY` | Groq API key for LLM chat |
| `DATABASE_URL` | Postgres connection string (from `bin/mc status`) |
## Architecture
```
Host (WSL2) Incus Containers
┌──────────────────────┐ ┌──────────────────────────────┐
│ Elixir App │ │ mc-fun-mc (Ubuntu Noble) │
│ Phoenix :4000 │───>│ Paper 1.21.4 + Java 21 │
│ McFun.Rcon (:25575) │ Game :25565 RCON :25575 │
│ McFun.Bot (:25565) │ 4GB RAM / 4 CPU │
│ │ └──────────────────────────────┘
│ │ ┌──────────────────────────────┐
│ │───>│ mc-fun-pg (Ubuntu Noble) │
│ │ │ Postgres 18 + TimescaleDB │
└──────────────────────┘ │ Port :5432 │
│ 1GB RAM / 2 CPU │
└──────────────────────────────┘
Phoenix LiveView Dashboard (/dashboard)
|
|-- DashboardLive -------- Parent LiveView (tab routing, PubSub, shared state)
| |-- UnitsPanelLive Bot deploy, cards, spawn/stop, online players
| |-- RconConsoleLive RCON terminal, history, quick commands
| |-- EventStreamLive Real-time event log
| |-- EffectsPanelLive Effects, titles, block text display
| |-- ChatPanelLive Color-coded chat log
| |-- MapPanelLive World map (terrain scan + Canvas 2D)
| +-- BotConfigModalLive Bot config modal (model, personality, behaviors)
|
|-- McFun.Bot ------------ bridge.js (mineflayer + pathfinder, Erlang Port)
| |-- dig, place, equip, craft, drop, goto, follow, jump, sneak, attack
| +-- status: position, health, food, dimension (polled every 5s)
|
|-- McFun.ChatBot -------- Groq LLM API
| |-- !ask, !model, !models, !personality, !reset, !tp
| +-- whispers always get a response
|
|-- McFun.ActionParser --- LLM response -> bot action (regex + tool calling)
|-- McFun.BotBehaviors --- patrol / follow / guard (1s tick GenServers)
|-- McFun.Presets -------- 22 bot personalities across 6 categories
|-- McFun.SNBT ----------- NBT text -> Elixir maps/lists (recursive descent)
|-- McFun.Rcon ----------- Minecraft Server (RCON)
|-- McFun.World.Effects --- title, firework, particle, sound effects
+-- McFun.World.Display --- Block text rendering
```
## In-Game Commands
| Command | Description |
|---------|-------------|
| `!ask <question>` | Ask the bot's LLM — bot performs actions it describes |
| `!model <id>` | Switch the bot's LLM model |
| `!models` | List available models |
| `!personality <text>` | Change the bot's personality |
| `!reset` | Clear conversation history |
| `!tp [player]` | Teleport bot to a player |
| `/msg BotName <text>` | Whisper to bot (always gets a response) |
## Dashboard Tabs
| Tab | Description |
|-----|-------------|
| **UNITS** | Bot cards (HP, food, position, model, cost, activity, behavior, job queue), deploy panel, config modal, collapsible online players section |
| **RCON** | Command terminal, history (arrow keys), Tab-repeat, quick command palette |
| **FX** | Entity picker, effect buttons, custom title/subtitle, block text display with entity-based coordinate fill |
| **EVENTS** | Real-time event stream |
| **CHAT** | Color-coded chat log (player, whisper, LLM, bot-to-bot, system) |
| **MAP** | World map from bot chunk data — terrain scan, height-shaded Canvas 2D, live bot/player overlays, zoom + pan |
### World Map

The MAP tab renders terrain from a bot's loaded chunks via mineflayer. Select a bot, hit SCAN, and the surface blocks are rendered onto an HTML Canvas with height-based shading. Bot and player positions update in real-time. Scroll to zoom (0.25x–16x), drag to pan.
## CLI Tools
```bash
# Server interaction
mix mc.cmd "say hello" # arbitrary RCON command
mix mc.players # list online players
mix mc.say Hello world! # broadcast chat message
mix mc.give Player diamond 64 # give item to player
mix mc.tp Player 0 64 0 # teleport player
mix mc.weather clear # set weather
mix mc.time day # set time of day
mix mc.gamemode creative @a # set gamemode
mix mc.effect @a speed 30 2 # give effect (duration, amplifier)
mix mc.heal @a # full heal + feed
# Effects & titles
mix mc.fx title @a "Hello" "subtitle" # title screen message
mix mc.fx welcome @a # welcome effect (title + sound)
mix mc.fx celebration @a # celebration effect
mix mc.fx firework @a # firework
mix mc.fx sound @a block.note_block.harp # play sound
mix mc.fx particle @a flame # particle effect
# Observability
mix mc.status # system health check
mix mc.events # live event watcher (Ctrl+C to stop)
```
## Testing
```bash
mix test # unit tests (excludes smoke tests)
mix test apps/mc_fun/test --only smoke # smoke tests (require live RCON)
mix precommit # compile + format + credo + test
```
## Tech Stack
- Elixir / Phoenix 1.8 / LiveView 1.1
- Node.js (mineflayer + mineflayer-pathfinder bridge)
- Groq API (LLM)
- Tailwind CSS
- Incus containers (Paper MC server, Postgres + TimescaleDB)
- No database yet — all state in-memory (Postgres provisioned for future event store)