0
# Container Management
1
2
Specialized interfaces for interacting with chests, furnaces, enchantment tables, villagers, and other container blocks with type-safe operations and automated management capabilities.
3
4
## Capabilities
5
6
### Chest Interaction
7
8
Open and interact with chests, trapped chests, and ender chests for storage management.
9
10
```typescript { .api }
11
/**
12
* Open a chest or chest-like container
13
* @param chest - Chest block or entity to open
14
* @param direction - Direction vector for interaction
15
* @param cursorPos - Precise cursor position
16
* @returns Promise resolving to Chest interface
17
*/
18
openChest(chest: Block | Entity, direction?: number, cursorPos?: Vec3): Promise<Chest>;
19
20
/**
21
* Open any container (chest, dispenser, etc.)
22
* @param container - Container block or entity
23
* @param direction - Direction vector for interaction
24
* @param cursorPos - Precise cursor position
25
* @returns Promise resolving to container interface
26
*/
27
openContainer(chest: Block | Entity, direction?: Vec3, cursorPos?: Vec3): Promise<Chest | Dispenser>;
28
29
interface Chest extends Window<StorageEvents> {
30
/** Close the chest */
31
close(): void;
32
33
/** Deposit items into chest */
34
deposit(itemType: number, metadata: number | null, count: number | null): Promise<void>;
35
36
/** Withdraw items from chest */
37
withdraw(itemType: number, metadata: number | null, count: number | null): Promise<void>;
38
}
39
```
40
41
**Usage Examples:**
42
43
```typescript
44
// Find and open nearest chest
45
const chest = bot.findBlock({
46
matching: bot.registry.blocksByName.chest.id,
47
maxDistance: 16
48
});
49
50
if (chest) {
51
const chestWindow = await bot.openChest(chest);
52
53
// Deposit cobblestone
54
await chestWindow.deposit(
55
bot.registry.itemsByName.cobblestone.id,
56
null,
57
64
58
);
59
60
// Withdraw diamonds
61
await chestWindow.withdraw(
62
bot.registry.itemsByName.diamond.id,
63
null,
64
5
65
);
66
67
chestWindow.close();
68
}
69
70
// Mass storage management
71
async function storeAllCobblestone() {
72
const chest = await bot.openChest(chestBlock);
73
const cobblestone = bot.inventory.items().filter(item => item.name === "cobblestone");
74
75
for (const item of cobblestone) {
76
await chest.deposit(item.type, item.metadata, item.count);
77
}
78
79
chest.close();
80
}
81
```
82
83
### Furnace Operations
84
85
Interact with furnaces for smelting and cooking operations.
86
87
```typescript { .api }
88
/**
89
* Open a furnace for smelting operations
90
* @param furnace - Furnace block to open
91
* @returns Promise resolving to Furnace interface
92
*/
93
openFurnace(furnace: Block): Promise<Furnace>;
94
95
interface Furnace extends Window<FurnaceEvents> {
96
/** Current fuel level (0-1) */
97
fuel: number;
98
/** Smelting progress (0-1) */
99
progress: number;
100
101
/** Close the furnace */
102
close(): void;
103
104
/** Take item from input slot */
105
takeInput(): Promise<Item>;
106
107
/** Take item from fuel slot */
108
takeFuel(): Promise<Item>;
109
110
/** Take item from output slot */
111
takeOutput(): Promise<Item>;
112
113
/** Put item in input slot */
114
putInput(itemType: number, metadata: number | null, count: number): Promise<void>;
115
116
/** Put item in fuel slot */
117
putFuel(itemType: number, metadata: number | null, count: number): Promise<void>;
118
119
/** Get current input item */
120
inputItem(): Item;
121
122
/** Get current fuel item */
123
fuelItem(): Item;
124
125
/** Get current output item */
126
outputItem(): Item;
127
}
128
129
interface FurnaceEvents extends StorageEvents {
130
/** Furnace state updated */
131
update(): void;
132
}
133
```
134
135
**Usage Examples:**
136
137
```typescript
138
// Automated smelting operation
139
const furnace = bot.findBlock({
140
matching: bot.registry.blocksByName.furnace.id,
141
maxDistance: 16
142
});
143
144
if (furnace) {
145
const furnaceWindow = await bot.openFurnace(furnace);
146
147
// Put iron ore in input
148
await furnaceWindow.putInput(
149
bot.registry.itemsByName.iron_ore.id,
150
null,
151
64
152
);
153
154
// Put coal as fuel
155
await furnaceWindow.putFuel(
156
bot.registry.itemsByName.coal.id,
157
null,
158
8
159
);
160
161
// Monitor smelting progress
162
furnaceWindow.on("update", () => {
163
console.log(`Fuel: ${(furnaceWindow.fuel * 100).toFixed(1)}%`);
164
console.log(`Progress: ${(furnaceWindow.progress * 100).toFixed(1)}%`);
165
166
// Take output when ready
167
if (furnaceWindow.progress === 1 && furnaceWindow.outputItem()) {
168
furnaceWindow.takeOutput().then(() => {
169
console.log("Took smelted iron ingot!");
170
});
171
}
172
});
173
}
174
175
// Batch smelting with automation
176
async function autoSmelt(inputItemType: number, fuelItemType: number, count: number) {
177
const furnaceWindow = await bot.openFurnace(furnaceBlock);
178
179
await furnaceWindow.putInput(inputItemType, null, count);
180
await furnaceWindow.putFuel(fuelItemType, null, Math.ceil(count / 8));
181
182
return new Promise<void>((resolve) => {
183
let outputCount = 0;
184
185
furnaceWindow.on("update", async () => {
186
if (furnaceWindow.outputItem()) {
187
await furnaceWindow.takeOutput();
188
outputCount++;
189
190
if (outputCount >= count) {
191
furnaceWindow.close();
192
resolve();
193
}
194
}
195
});
196
});
197
}
198
```
199
200
### Dispenser and Dropper Management
201
202
Interact with dispensers and droppers for item distribution.
203
204
```typescript { .api }
205
/**
206
* Open a dispenser for item management
207
* @param dispenser - Dispenser block to open
208
* @returns Promise resolving to Dispenser interface
209
*/
210
openDispenser(dispenser: Block): Promise<Dispenser>;
211
212
interface Dispenser extends Window<StorageEvents> {
213
/** Close the dispenser */
214
close(): void;
215
216
/** Deposit items into dispenser */
217
deposit(itemType: number, metadata: number | null, count: number | null): Promise<void>;
218
219
/** Withdraw items from dispenser */
220
withdraw(itemType: number, metadata: number | null, count: number | null): Promise<void>;
221
}
222
```
223
224
### Enchantment Table Operations
225
226
Use enchantment tables for enchanting items and managing lapis lazuli.
227
228
```typescript { .api }
229
/**
230
* Open an enchantment table for enchanting operations
231
* @param enchantmentTable - Enchantment table block
232
* @returns Promise resolving to EnchantmentTable interface
233
*/
234
openEnchantmentTable(enchantmentTable: Block): Promise<EnchantmentTable>;
235
236
interface EnchantmentTable extends Window<ConditionalStorageEvents> {
237
/** Available enchantments */
238
enchantments: Enchantment[];
239
240
/** Close the enchantment table */
241
close(): void;
242
243
/** Get the target item being enchanted */
244
targetItem(): Item;
245
246
/** Apply enchantment by choice */
247
enchant(choice: string | number): Promise<Item>;
248
249
/** Take the target item */
250
takeTargetItem(): Promise<Item>;
251
252
/** Put item to enchant */
253
putTargetItem(item: Item): Promise<Item>;
254
255
/** Put lapis lazuli for enchanting */
256
putLapis(item: Item): Promise<Item>;
257
}
258
259
interface ConditionalStorageEvents extends StorageEvents {
260
/** Enchantment table is ready for use */
261
ready(): void;
262
}
263
264
interface Enchantment {
265
/** Required experience level */
266
level: number;
267
/** Expected enchantment result */
268
expected: { enchant: number; level: number };
269
}
270
```
271
272
**Usage Examples:**
273
274
```typescript
275
// Enchant a sword
276
const enchantmentTable = bot.findBlock({
277
matching: bot.registry.blocksByName.enchanting_table.id,
278
maxDistance: 16
279
});
280
281
if (enchantmentTable) {
282
const table = await bot.openEnchantmentTable(enchantmentTable);
283
284
// Wait for table to be ready
285
await new Promise<void>((resolve) => {
286
table.on("ready", resolve);
287
});
288
289
// Put sword to enchant
290
const sword = bot.inventory.findItem("diamond_sword");
291
if (sword) {
292
await table.putTargetItem(sword);
293
294
// Put lapis lazuli
295
const lapis = bot.inventory.findItem("lapis_lazuli");
296
if (lapis) {
297
await table.putLapis(lapis);
298
299
// Choose best enchantment
300
if (table.enchantments.length > 0) {
301
const bestEnchant = table.enchantments.reduce((best, current) =>
302
current.level > best.level ? current : best
303
);
304
305
const enchantedItem = await table.enchant(bestEnchant.level);
306
console.log(`Enchanted ${enchantedItem.name}!`);
307
}
308
}
309
}
310
311
table.close();
312
}
313
```
314
315
### Anvil Operations
316
317
Use anvils for combining and renaming items.
318
319
```typescript { .api }
320
/**
321
* Open an anvil for item combination and renaming
322
* @param anvil - Anvil block to open
323
* @returns Promise resolving to Anvil interface
324
*/
325
openAnvil(anvil: Block): Promise<Anvil>;
326
327
interface Anvil {
328
/** Combine two items */
329
combine(itemOne: Item, itemTwo: Item, name?: string): Promise<void>;
330
331
/** Rename an item */
332
rename(item: Item, name?: string): Promise<void>;
333
}
334
```
335
336
### Villager Trading
337
338
Trade with villagers using their trade offers.
339
340
```typescript { .api }
341
/**
342
* Open villager trading interface
343
* @param villager - Villager entity to trade with
344
* @returns Promise resolving to Villager interface
345
*/
346
openVillager(villager: Entity): Promise<Villager>;
347
348
/**
349
* Execute a trade with a villager
350
* @param villagerInstance - Villager trading window
351
* @param tradeIndex - Trade offer index or ID
352
* @param times - Number of times to execute trade
353
* @returns Promise that resolves when trading completes
354
*/
355
trade(villagerInstance: Villager, tradeIndex: string | number, times?: number): Promise<void>;
356
357
interface Villager extends Window<ConditionalStorageEvents> {
358
/** Available trade offers */
359
trades: VillagerTrade[];
360
361
/** Close trading interface */
362
close(): void;
363
}
364
365
interface VillagerTrade {
366
/** First input item required */
367
inputItem1: Item;
368
/** Output item offered */
369
outputItem: Item;
370
/** Second input item (optional) */
371
inputItem2: Item | null;
372
/** Whether second item is required */
373
hasItem2: boolean;
374
/** Whether this trade is disabled */
375
tradeDisabled: boolean;
376
/** Number of times trade has been used */
377
nbTradeUses: number;
378
/** Maximum number of times trade can be used */
379
maximumNbTradeUses: number;
380
/** Experience gained from trade */
381
xp?: number;
382
/** Special price adjustment */
383
specialPrice?: number;
384
/** Price multiplier */
385
priceMultiplier?: number;
386
/** Demand level */
387
demand?: number;
388
/** Real calculated price */
389
realPrice?: number;
390
}
391
```
392
393
**Usage Examples:**
394
395
```typescript
396
// Find and trade with librarian
397
const librarian = bot.nearestEntity(entity =>
398
entity.name === "villager" &&
399
entity.metadata[13] === 1 // Librarian profession
400
);
401
402
if (librarian) {
403
const villagerWindow = await bot.openVillager(librarian);
404
405
// Wait for trades to load
406
await new Promise<void>((resolve) => {
407
villagerWindow.on("ready", resolve);
408
});
409
410
// Find enchanted book trade
411
const bookTrade = villagerWindow.trades.find(trade =>
412
trade.outputItem.name === "enchanted_book"
413
);
414
415
if (bookTrade && !bookTrade.tradeDisabled) {
416
// Check if we have required items
417
const hasFirstItem = bot.inventory.count(bookTrade.inputItem1.type) >= bookTrade.inputItem1.count;
418
const hasSecondItem = !bookTrade.hasItem2 ||
419
bot.inventory.count(bookTrade.inputItem2!.type) >= bookTrade.inputItem2!.count;
420
421
if (hasFirstItem && hasSecondItem) {
422
await bot.trade(villagerWindow, 0, 1);
423
console.log("Traded for enchanted book!");
424
}
425
}
426
427
villagerWindow.close();
428
}
429
430
// Automated emerald farming with farmer
431
async function farmEmeralds() {
432
const farmer = bot.nearestEntity(entity =>
433
entity.name === "villager" &&
434
entity.metadata[13] === 0 // Farmer profession
435
);
436
437
if (farmer) {
438
const villagerWindow = await bot.openVillager(farmer);
439
await new Promise<void>(resolve => villagerWindow.on("ready", resolve));
440
441
// Find wheat -> emerald trade
442
const wheatTrade = villagerWindow.trades.find(trade =>
443
trade.inputItem1.name === "wheat" && trade.outputItem.name === "emerald"
444
);
445
446
if (wheatTrade) {
447
const wheatCount = bot.inventory.count(bot.registry.itemsByName.wheat.id);
448
const maxTrades = Math.min(
449
Math.floor(wheatCount / wheatTrade.inputItem1.count),
450
wheatTrade.maximumNbTradeUses - wheatTrade.nbTradeUses
451
);
452
453
if (maxTrades > 0) {
454
await bot.trade(villagerWindow, 0, maxTrades);
455
console.log(`Traded ${maxTrades} times for emeralds`);
456
}
457
}
458
459
villagerWindow.close();
460
}
461
}
462
```
463
464
### Generic Container Operations
465
466
Open any type of container with automatic type detection.
467
468
```typescript { .api }
469
/**
470
* Open a block as a window/container
471
* @param block - Block to open
472
* @param direction - Interaction direction
473
* @param cursorPos - Cursor position
474
* @returns Promise resolving to Window interface
475
*/
476
openBlock(block: Block, direction?: Vec3, cursorPos?: Vec3): Promise<Window>;
477
478
/**
479
* Open an entity as a window/container
480
* @param entity - Entity to open
481
* @param Class - Window class constructor
482
* @returns Promise resolving to Window interface
483
*/
484
openEntity(entity: Entity, Class: new () => EventEmitter): Promise<Window>;
485
486
/**
487
* Close any open window
488
* @param window - Window to close
489
*/
490
closeWindow(window: Window): void;
491
```
492
493
### Container Events
494
495
Monitor container interactions and state changes.
496
497
```typescript { .api }
498
interface BotEvents {
499
/** Container/window opened */
500
windowOpen(window: Window): void;
501
/** Container/window closed */
502
windowClose(window: Window): void;
503
}
504
505
// Monitor all container operations
506
bot.on("windowOpen", (window) => {
507
console.log(`Opened ${window.title} (${window.type})`);
508
});
509
510
bot.on("windowClose", (window) => {
511
console.log(`Closed ${window.title}`);
512
});
513
```