Examples
Each example assumes at least one Minecraft client is connected.
Get the first connected client
const clients = await script.getMcClients();
if (clients.length === 0) throw new Error('No Minecraft client connected');
const mc = script.getMcClient(clients[0].clientId);
Reply to chat
const [{ clientId }] = await script.getMcClients();
const mc = script.getMcClient(clientId);
await mc.on('chat', async ({ message, kind }) => {
if (kind !== 'chat') return;
if (!message.toLowerCase().includes('hello')) return;
await mc.chat('Hello!');
});
Move for two seconds
const [{ clientId }] = await script.getMcClients();
const mc = script.getMcClient(clientId);
await mc.setMovement({ forward: true, sprint: true });
await new Promise((resolve) => setTimeout(resolve, 2_000));
await mc.setMovement({ forward: false, sprint: false });
Use a try and finally block when a plugin might fail while holding a key.
try {
await mc.setMovement({ forward: true });
await doWork();
} finally {
await mc.setMovement({ forward: false });
}
Rotate smoothly
const rotation = await mc.smoothLook({
yaw: 180,
pitch: -15,
durationMs: 1_200,
easing: 'easeInOut',
});
await mc.waitFor(
() => mc.smoothLookStatus(),
(status) => !status.active,
{ timeoutMs: 5_000, intervalMs: 100 },
);
console.log('Rotation finished:', rotation.taskId);
Find and approach a block
const [{ clientId }] = await script.getMcClients();
const mc = script.getMcClient(clientId);
const result = await mc.gotoBlock({
matching: ['minecraft:diamond_ore', 'minecraft:deepslate_diamond_ore'],
maxDistance: 48,
arriveRadius: 2,
sprint: true,
});
if (!result.ok) {
console.warn('Could not reach diamond ore:', result.reason);
return;
}
await mc.waitFor(
() => mc.pathStatus(),
(status) => !status.active,
{ timeoutMs: 60_000, intervalMs: 250 },
);
Navigate while flying
const result = await mc.goto({
x: 250,
y: 120,
z: -80,
movement: 'fly',
arriveRadius: 1.5,
});
if (!result.ok) console.warn(result.reason);
Use movement: 'auto' when the same plugin should work for both walking and
flying players.
Mine a vein
const ore = await mc.findBlock({
matching: ['minecraft:diamond_ore', 'minecraft:deepslate_diamond_ore'],
maxDistance: 32,
});
if (ore) {
await mc.veinMine({
...ore.position,
matching: ['minecraft:diamond_ore', 'minecraft:deepslate_diamond_ore'],
maxBlocks: 32,
autoTool: true,
movement: 'auto',
});
}
Follow the nearest player
const [{ clientId }] = await script.getMcClients();
const mc = script.getMcClient(clientId);
const player = await mc.nearestEntity({
type: 'minecraft:player',
radius: 64,
});
if (!player) {
console.log('No player found');
return;
}
const task = await mc.followEntity({
id: player.id,
distance: 3,
sprint: true,
});
console.log('Following with task:', task.taskId);
// Stop later without affecting a newer task.
await mc.stopTask(task.taskId);
Attack the nearest hostile entity
const target = await mc.nearestEntity({
hostile: true,
radius: 32,
});
if (target) {
const task = await mc.attackEntityUntilDead({
id: target.id,
distance: 3,
sprint: true,
});
await mc.waitFor(
() => mc.taskStatus(),
(status) => !status.active,
{ timeoutMs: 60_000, intervalMs: 250 },
);
console.log('Attack task finished:', task.taskId);
}
Count and equip an item
const diamonds = await mc.countInventoryItem('minecraft:diamond');
console.log(`The player has ${diamonds} diamonds`);
const helmets = await mc.findInventoryItems({
matching: 'diamond_helmet',
limit: 1,
});
if (helmets.items.length > 0) {
await mc.equip({
slot: helmets.items[0].slot,
destination: 'head',
});
}
Deposit matching items into a container
const window = await mc.getCurrentWindow();
if (!window) {
console.warn('Open a container first');
return;
}
const result = await mc.transferInventory({
from: 'player',
matching: 'minecraft:cobblestone',
limit: 64,
});
console.log(`Moved ${result.affected} stacks`);
React to block changes
const off = await mc.on('blockChanged', ({ watchId, changes }) => {
if (watchId !== 'crop-area') return;
for (const block of changes) {
console.log(`${block.blockId} changed at`, block.position);
}
});
await mc.watchBlocks({
id: 'crop-area',
from: { x: 100, y: 60, z: 100 },
to: { x: 115, y: 67, z: 115 },
intervalMs: 500,
});
// Later
await mc.unwatchBlocks('crop-area');
await off();
Create a plugin control screen
let autoFollow = false;
await mc.on('uiAction', async ({ uiId, elementId, action, value }) => {
if (uiId !== 'player-tools') return;
if (elementId === 'autoFollow' && action === 'change') {
autoFollow = value;
if (!autoFollow) {
await mc.stopTask();
return;
}
const target = await mc.nearestEntity({
type: 'minecraft:player',
radius: 64,
});
if (target) {
await mc.followEntity({ id: target.id, distance: 3 });
}
}
if (elementId === 'stop' && action === 'click') {
autoFollow = false;
await mc.stopTask();
await mc.stopPath();
}
});
await mc.openUi({
id: 'player-tools',
title: 'Player tools',
elements: [
{ type: 'label', label: 'Automation settings' },
{
type: 'toggle',
id: 'autoFollow',
label: 'Follow nearest player',
value: autoFollow,
},
{
type: 'button',
id: 'stop',
label: 'Stop movement',
},
],
});
Notify the player when an item count is reached
await mc.waitFor(
() => mc.countInventoryItem('minecraft:diamond'),
(count) => count >= 64,
{ timeoutMs: 10 * 60_000, intervalMs: 1_000 },
);
await mc.toast({
title: 'Diamond goal reached',
body: 'The inventory contains at least 64 diamonds.',
kind: 'ok',
});
await mc.beep();
await mc.flashWindow();
Mark found blocks in the world
const result = await mc.findBlocks({
matching: 'minecraft:ancient_debris',
maxDistance: 32,
count: 10,
});
for (const [index, block] of result.blocks.entries()) {
await mc.marker({
id: `debris-${index}`,
...block.position,
label: `Ancient debris ${index + 1}`,
color: '#f97316',
ttlMs: 60_000,
});
}
Control multiple clients
const clients = await script.getMcClients();
await Promise.all(
clients.map(async ({ clientId, username }) => {
const client = script.getMcClient(clientId);
await client.toast({
title: 'Plugin started',
body: username ?? clientId,
kind: 'info',
});
}),
);