Distributed headless mineflayer bot system for anarchy servers.
Architecture: Modular ES Modules
Runtime: Node.js 18+
Language: TypeScript 5.3
State: Singleton pattern with getter/setter access
| Command | Description |
|---|---|
npm run bot |
Start bot instance |
npm run cli |
Interactive CLI tool |
npx tsc --noEmit |
Type-check |
packages/
├── core/ # Orchestration layer
│ ├── bot.ts # Entry point
│ ├── config.ts # Centralized configuration
│ ├── connection.ts # Server connection logic
│ ├── events.ts # Event handlers
│ ├── lifecycle.ts # Bot lifecycle management
│ └── state.ts # Singleton state management
├── functions/ # Complex behaviors
│ └── orbit.ts # Orbital flight mechanics
├── storage/ # Persistence layer
│ └── database.ts # SQLite interface
├── tools/ # CLI tooling
│ └── cli.ts
└── utils/ # Implementation layer
├── chat.ts
├── inventoryManagement.ts
├── elytraMovement.ts
├── storageBlocks.ts
├── blockInteractions.ts
├── brand.ts
├── plugins.ts
└── commands/ # Whisper command handlers
Config.category.setting pattern. All hardcoded values centralized.
Config.server.host // '8b8t.me'
Config.server.version // '1.20.1'
Config.auth.type // 'offline'
Config.target.player // 'Raphiel'
Config.orbit.radius // 7
Config.elytra.maxSpeed // 40 (blocks/s)
Config.elytra.gravityCompensation // 0.02 (calibrated)
Config.security.allowedUsers // ['user1', 'user2']Centralized via packages/core/state.ts.
// Getters
State.isLoggedIn() // boolean
State.isReady() // boolean
State.getCurrentWorld() // 'none' | 'lobby' | 'survival'
State.isElytraDeployed() // boolean
State.getCurrentStorage() // Container | null
// Setters
State.setLoggedIn(true)
State.setReady(true)
State.enterLobby()
State.enterSurvival()
State.setElytraDeployed(true)// Deployment
ElytraMovement.hoverElytra(bot) // 0-gravity hover
ElytraMovement.deployElytra(bot) // Standard flight
// Movement
ElytraMovement.moveElytra(bot, direction, blocks)
// direction: 'up' | 'down' | 'left' | 'right' | 'forward' | 'backward'
// State validation
ElytraMovement.isActuallyDeployed(bot) // Heuristic detection
ElytraMovement.validateElytraState(bot) // Auto-correct if mismatched
// Control
ElytraMovement.stopElytra(bot)
ElytraMovement.forceStopElytra(bot)
ElytraMovement.setElytraControl(bot, state, value)Implementation Details:
- Custom physics tick overrides plugin default (forces +0.07545 Y/tick)
- Gravity compensation:
0.02blocks/tick (calibrated for 8b8t) - Altitude lock during horizontal movement
- 500ms post-movement correction phase
- Speed: proportional to distance, clamped 5-40 blocks/s
Whisper-based command interface.
// Registration (packages/utils/commands/index.ts)
import * as elytra from './elytra.js';
registerCommand(elytra.name, elytra.execute);
// Handler signature
export function execute(
bot: mineflayer.Bot,
username: string,
args: string[]
): void | Promise<void>Available Commands:
| Command | Args | Description |
|---|---|---|
!elytra |
- | Deploy elytra (0-gravity hover) |
!elytra up |
[blocks=1] |
Move up N blocks |
!elytra down |
[blocks=1] |
Move down N blocks |
!elytra forward |
[blocks=1] |
Move forward N blocks |
!elytra backward |
[blocks=1] |
Move backward N blocks |
!elytra left |
[blocks=1] |
Move left N blocks |
!elytra right |
[blocks=1] |
Move right N blocks |
!drop |
<item> [count] |
Drop items from inventory |
!say |
<message> |
Send chat message |
!placeBlock |
- | Place held block |
!takeItem |
<item> |
Take item from storage |
!testInventory |
- | Debug inventory state |
// Slot ranges
SLOTS.ARMOR_TORSO // 6 (elytra slot)
SLOTS.HOTBAR_START // 36
SLOTS.HOTBAR_END // 44
SLOTS.OFFHAND // 45
// Operations
Inventory.findItem(bot, 'elytra')
Inventory.equipElytra(bot) // Promise<boolean>
Inventory.getHeldItem(bot)
Inventory.getArmor(bot)
Inventory.dropItem(bot, itemName, count)Intercepts minecraft:brand custom_payload packet.
// Spoofs to 'vanilla' to avoid detection
const clientWrite = bot._client.write.bind(bot._client);
bot._client.write = function(name: string, params: unknown): void {
if (name === 'custom_payload' && isBrandPayload(params)) {
const vanillaBuf = Buffer.concat([
Buffer.from([7]),
Buffer.from('vanilla')
]);
clientWrite(name, { channel: 'minecraft:brand', data: vanillaBuf });
return;
}
clientWrite(name, params);
};Dual-spawn detection for networked servers with login plugins.
Spawn 1 (none → lobby) : Initial connection, send /login
Spawn 2 (lobby → survival) : Post-teleport, bot is "logged in"
bot.on('spawn', () => {
if (State.getCurrentWorld() === 'none') {
State.enterLobby();
Chat.sendLogin(bot, password);
} else if (State.getCurrentWorld() === 'lobby') {
State.enterSurvival();
// Begin bot behavior
}
});bot.ts (top level)
↓
core modules (orchestration)
↓
functions / utils (implementation)
↓
storage (persistence)
Lower levels NEVER import from higher levels.
| Prefix | Usage |
|---|---|
[FATAL] |
Unrecoverable error, exit code 1 |
[ERROR] |
Recoverable error |
[WARN] |
Warning, non-critical |
[INFO] |
General information |
[CMD] |
Command execution |
[CHAT] |
Chat message logging |
Elytra Physics:
- Plugin default:
+0.07545Y/tick (causes rapid ascent) - Fix: Override
onTick, set Y velocity directly to0.02 - Horizontal drift fix: Lock altitude + 500ms correction phase
State Validation:
const actualDeployed = pluginFlying || (elytraEquipped && !onGround);Momentum Cancellation:
// Wrong - accumulates momentum
vel.y += GRAVITY_COMPENSATION;
// Correct - cancels momentum
bot.entity.velocity.set(vel.x, GRAVITY_COMPENSATION, vel.z);Full discoveries: docs/discoveries.md
- Use
anyfor mineflayer/prismarine types (no exports) - Always
.jsextension in imports (ES modules) - No
@ts-ignorewithout understanding why - Run
npx tsc --noEmitbefore commit
feat: New feature
fix: Bug fix
refactor: Code change, same behavior
docs: Documentation only
chore: Build/tooling changes
One logical change per commit. Keep messages under 72 characters.
