0
# NBT and Data Components
1
2
NBT (Named Binary Tag) data handling with serialization support and integration with Minecraft's data component system. Adventure provides comprehensive NBT support for complex data structures.
3
4
## Capabilities
5
6
### Binary Tag Holder
7
8
Interface for holding and managing NBT binary tag data with serialization support.
9
10
```java { .api }
11
/**
12
* Holds NBT binary tag data with serialization support
13
*/
14
interface BinaryTagHolder extends Examinable {
15
/**
16
* Gets the binary tag data
17
* @return the binary tag
18
* @throws IOException if data cannot be read
19
*/
20
@NotNull BinaryTag get() throws IOException;
21
22
/**
23
* Gets the NBT data as a string representation
24
* @return the string representation
25
*/
26
String string();
27
28
/**
29
* Encodes a binary tag into a holder
30
* @param nbt the binary tag to encode
31
* @return new binary tag holder
32
*/
33
static BinaryTagHolder encode(BinaryTag nbt);
34
35
/**
36
* Creates a holder from an NBT string
37
* @param string the NBT string
38
* @return new binary tag holder
39
*/
40
static BinaryTagHolder of(String string);
41
42
/**
43
* Creates an empty binary tag holder
44
* @return empty holder
45
*/
46
static BinaryTagHolder empty();
47
}
48
```
49
50
### NBT Component Interface
51
52
Base interface for components that display NBT data from various sources.
53
54
```java { .api }
55
/**
56
* Base interface for components displaying NBT data
57
*/
58
interface NBTComponent<C extends NBTComponent<C, B>, B extends NBTComponentBuilder<C, B>>
59
extends BuildableComponent<C, B> {
60
61
/**
62
* Gets the NBT path expression
63
* @return the NBT path
64
*/
65
String nbtPath();
66
67
/**
68
* Gets whether to interpret NBT as text components
69
* @return true if should interpret as components
70
*/
71
boolean interpret();
72
73
/**
74
* Gets the separator for multiple NBT results
75
* @return the separator component or null
76
*/
77
@Nullable Component separator();
78
79
/**
80
* Sets the NBT path expression
81
* @param nbtPath the path
82
* @return component with new path
83
*/
84
C nbtPath(String nbtPath);
85
86
/**
87
* Sets whether to interpret NBT as components
88
* @param interpret whether to interpret
89
* @return component with new interpret setting
90
*/
91
C interpret(boolean interpret);
92
93
/**
94
* Sets the separator for multiple NBT results
95
* @param separator the separator or null
96
* @return component with new separator
97
*/
98
C separator(@Nullable ComponentLike separator);
99
}
100
```
101
102
### Block NBT Component
103
104
Component that displays NBT data from a block at a specific position.
105
106
```java { .api }
107
/**
108
* Component displaying block NBT data
109
*/
110
interface BlockNBTComponent extends NBTComponent<BlockNBTComponent, BlockNBTComponent.Builder> {
111
/**
112
* Gets the block position
113
* @return the position
114
*/
115
Pos pos();
116
117
/**
118
* Sets the block position
119
* @param pos the new position
120
* @return component with new position
121
*/
122
BlockNBTComponent pos(Pos pos);
123
124
/**
125
* Creates a block NBT component
126
* @param nbtPath the NBT path
127
* @param pos the block position
128
* @return new block NBT component
129
*/
130
static BlockNBTComponent blockNBT(String nbtPath, Pos pos);
131
132
/**
133
* Block position for NBT access
134
*/
135
interface Pos extends Examinable {
136
/**
137
* Gets the X coordinate
138
* @return the X coordinate
139
*/
140
int x();
141
142
/**
143
* Gets the Y coordinate
144
* @return the Y coordinate
145
*/
146
int y();
147
148
/**
149
* Gets the Z coordinate
150
* @return the Z coordinate
151
*/
152
int z();
153
154
/**
155
* Creates a block position
156
* @param x the X coordinate
157
* @param y the Y coordinate
158
* @param z the Z coordinate
159
* @return new position
160
*/
161
static Pos of(int x, int y, int z);
162
163
/**
164
* Creates an absolute position
165
* @param x the X coordinate
166
* @param y the Y coordinate
167
* @param z the Z coordinate
168
* @return new absolute position
169
*/
170
static Pos absolute(int x, int y, int z);
171
172
/**
173
* Creates a relative position
174
* @param x the X offset
175
* @param y the Y offset
176
* @param z the Z offset
177
* @return new relative position
178
*/
179
static Pos relative(int x, int y, int z);
180
}
181
182
interface Builder extends NBTComponentBuilder<BlockNBTComponent, Builder> {
183
/**
184
* Sets the block position
185
* @param pos the position
186
* @return this builder
187
*/
188
Builder pos(Pos pos);
189
}
190
}
191
```
192
193
### Entity NBT Component
194
195
Component that displays NBT data from entities matching a selector.
196
197
```java { .api }
198
/**
199
* Component displaying entity NBT data
200
*/
201
interface EntityNBTComponent extends NBTComponent<EntityNBTComponent, EntityNBTComponent.Builder> {
202
/**
203
* Gets the entity selector
204
* @return the selector string
205
*/
206
String selector();
207
208
/**
209
* Sets the entity selector
210
* @param selector the new selector
211
* @return component with new selector
212
*/
213
EntityNBTComponent selector(String selector);
214
215
/**
216
* Creates an entity NBT component
217
* @param nbtPath the NBT path
218
* @param selector the entity selector
219
* @return new entity NBT component
220
*/
221
static EntityNBTComponent entityNBT(String nbtPath, String selector);
222
223
interface Builder extends NBTComponentBuilder<EntityNBTComponent, Builder> {
224
/**
225
* Sets the entity selector
226
* @param selector the selector
227
* @return this builder
228
*/
229
Builder selector(String selector);
230
}
231
}
232
```
233
234
### Storage NBT Component
235
236
Component that displays NBT data from command storage.
237
238
```java { .api }
239
/**
240
* Component displaying command storage NBT data
241
*/
242
interface StorageNBTComponent extends NBTComponent<StorageNBTComponent, StorageNBTComponent.Builder> {
243
/**
244
* Gets the storage key
245
* @return the storage key
246
*/
247
Key storage();
248
249
/**
250
* Sets the storage key
251
* @param storage the new storage key
252
* @return component with new storage key
253
*/
254
StorageNBTComponent storage(Key storage);
255
256
/**
257
* Creates a storage NBT component
258
* @param nbtPath the NBT path
259
* @param storage the storage key
260
* @return new storage NBT component
261
*/
262
static StorageNBTComponent storageNBT(String nbtPath, Key storage);
263
264
interface Builder extends NBTComponentBuilder<StorageNBTComponent, Builder> {
265
/**
266
* Sets the storage key
267
* @param storage the storage key
268
* @return this builder
269
*/
270
Builder storage(Key storage);
271
}
272
}
273
```
274
275
### NBT Component Builder
276
277
Specialized builder interface for NBT components.
278
279
```java { .api }
280
/**
281
* Specialized builder for NBT components
282
*/
283
interface NBTComponentBuilder<C extends NBTComponent<C, B>, B extends NBTComponentBuilder<C, B>>
284
extends ComponentBuilder<C, B> {
285
286
/**
287
* Sets the NBT path expression
288
* @param nbtPath the path
289
* @return this builder
290
*/
291
B nbtPath(String nbtPath);
292
293
/**
294
* Sets whether to interpret NBT as components
295
* @param interpret whether to interpret
296
* @return this builder
297
*/
298
B interpret(boolean interpret);
299
300
/**
301
* Sets the separator for multiple NBT results
302
* @param separator the separator or null
303
* @return this builder
304
*/
305
B separator(@Nullable ComponentLike separator);
306
}
307
```
308
309
**Usage Examples:**
310
311
```java
312
import net.kyori.adventure.text.Component;
313
import net.kyori.adventure.nbt.api.BinaryTagHolder;
314
import net.kyori.adventure.key.Key;
315
316
// Block NBT component showing a sign's text
317
Component signText = Component.blockNBT(
318
"front_text.messages[0]",
319
BlockNBTComponent.Pos.absolute(100, 64, 200)
320
);
321
322
// Entity NBT component showing player's health
323
Component playerHealth = Component.entityNBT(
324
"Health",
325
"@p" // Nearest player selector
326
);
327
328
// Storage NBT component from command storage
329
Component storedValue = Component.storageNBT(
330
"custom_data.score",
331
Key.key("myserver", "player_data")
332
);
333
334
// NBT component with interpretation and separator
335
Component inventoryDisplay = Component.blockNBT()
336
.nbtPath("Items[].tag.display.Name")
337
.pos(BlockNBTComponent.Pos.relative(0, -1, 0))
338
.interpret(true) // Interpret NBT as text components
339
.separator(Component.text(", "))
340
.build();
341
342
// Binary tag holder usage
343
String nbtString = "{id:\"minecraft:diamond_sword\",Count:1b}";
344
BinaryTagHolder holder = BinaryTagHolder.of(nbtString);
345
346
// Use in hover events
347
Component itemDisplay = Component.text("Diamond Sword")
348
.hoverEvent(HoverEvent.showItem(
349
Key.key("minecraft:diamond_sword"),
350
1,
351
holder
352
));
353
```
354
355
## NBT Path Expressions
356
357
NBT path expressions allow precise selection of data from NBT structures:
358
359
### Basic Path Syntax
360
361
```java
362
// Simple field access
363
"Health" // Root field
364
"Inventory[0]" // Array element
365
"CustomName" // String field
366
367
// Nested field access
368
"tag.display.Name" // Nested object fields
369
"Items[0].tag.Damage" // Array element with nested field
370
"Attributes[{Name:\"generic.max_health\"}].Base" // Filtered array access
371
372
// Multiple results
373
"Inventory[].id" // All item IDs in inventory
374
"Effects[].Id" // All potion effect IDs
375
```
376
377
### Advanced Path Examples
378
379
```java
380
public class NBTPathExamples {
381
// Player data access
382
public static Component getPlayerLevel() {
383
return Component.entityNBT("XpLevel", "@s");
384
}
385
386
public static Component getPlayerGamemode() {
387
return Component.entityNBT("playerGameType", "@s");
388
}
389
390
// Inventory item display
391
public static Component getHeldItemName() {
392
return Component.entityNBT(
393
"SelectedItem.tag.display.Name",
394
"@s"
395
).interpret(true);
396
}
397
398
// Block data access
399
public static Component getChestContents(int x, int y, int z) {
400
return Component.blockNBT(
401
"Items[].tag.display.Name",
402
BlockNBTComponent.Pos.absolute(x, y, z)
403
).interpret(true)
404
.separator(Component.text(", "));
405
}
406
407
// Sign text access
408
public static Component getSignLine(int x, int y, int z, int line) {
409
return Component.blockNBT(
410
"front_text.messages[" + line + "]",
411
BlockNBTComponent.Pos.absolute(x, y, z)
412
).interpret(true);
413
}
414
415
// Command storage access
416
public static Component getStoredPlayerName(String playerId) {
417
return Component.storageNBT(
418
"players." + playerId + ".name",
419
Key.key("myserver", "playerdata")
420
);
421
}
422
}
423
```
424
425
## Data Component Integration
426
427
### Modern Data Component System
428
429
```java
430
public class DataComponentIntegration {
431
// Item data component access
432
public static Component getItemName() {
433
return Component.entityNBT(
434
"SelectedItem.components.\"minecraft:item_name\"",
435
"@s"
436
).interpret(true);
437
}
438
439
public static Component getItemLore() {
440
return Component.entityNBT(
441
"SelectedItem.components.\"minecraft:lore\"[]",
442
"@s"
443
).interpret(true)
444
.separator(Component.newline());
445
}
446
447
// Custom data component
448
public static Component getCustomData(String path) {
449
return Component.entityNBT(
450
"SelectedItem.components.\"minecraft:custom_data\"." + path,
451
"@s"
452
);
453
}
454
455
// Enchantment data
456
public static Component getEnchantments() {
457
return Component.entityNBT(
458
"SelectedItem.components.\"minecraft:enchantments\".levels",
459
"@s"
460
);
461
}
462
}
463
```
464
465
### NBT Data Validation
466
467
```java
468
public class NBTValidator {
469
public static boolean isValidNBTPath(String path) {
470
// Basic NBT path validation
471
if (path == null || path.isEmpty()) {
472
return false;
473
}
474
475
// Check for valid characters and structure
476
return path.matches("^[a-zA-Z0-9_.\\[\\]{}\"':@-]+$");
477
}
478
479
public static boolean isValidSelector(String selector) {
480
// Basic entity selector validation
481
return selector != null &&
482
(selector.startsWith("@") || selector.matches("^[a-zA-Z0-9_-]+$"));
483
}
484
485
public static BinaryTagHolder sanitizeNBT(BinaryTagHolder holder) {
486
try {
487
BinaryTag tag = holder.get();
488
489
// Validate and sanitize NBT data
490
if (isValidNBTStructure(tag)) {
491
return holder;
492
} else {
493
return BinaryTagHolder.empty();
494
}
495
} catch (IOException e) {
496
return BinaryTagHolder.empty();
497
}
498
}
499
500
private static boolean isValidNBTStructure(BinaryTag tag) {
501
// Implement NBT structure validation
502
// Check for malicious or oversized data
503
return true; // Simplified
504
}
505
}
506
```
507
508
## Performance Considerations
509
510
### NBT Access Optimization
511
512
```java
513
public class NBTOptimization {
514
// Cache frequently accessed NBT paths
515
private static final Map<String, Component> NBT_CACHE = new ConcurrentHashMap<>();
516
517
public static Component getCachedNBT(String cacheKey, Supplier<Component> nbtSupplier) {
518
return NBT_CACHE.computeIfAbsent(cacheKey, k -> nbtSupplier.get());
519
}
520
521
// Batch NBT operations
522
public static List<Component> getBatchedBlockNBT(List<BlockNBTRequest> requests) {
523
return requests.parallelStream()
524
.map(req -> Component.blockNBT(req.path(), req.pos()))
525
.collect(Collectors.toList());
526
}
527
528
// Lazy NBT evaluation
529
public static Component createLazyNBT(String path, String selector) {
530
return Component.text("[Loading...]")
531
.hoverEvent(HoverEvent.showText(
532
Component.entityNBT(path, selector)
533
));
534
}
535
536
// Efficient NBT string building
537
public static String buildNBTString(Map<String, Object> data) {
538
StringBuilder nbt = new StringBuilder("{");
539
boolean first = true;
540
541
for (Map.Entry<String, Object> entry : data.entrySet()) {
542
if (!first) nbt.append(",");
543
nbt.append(entry.getKey()).append(":").append(formatNBTValue(entry.getValue()));
544
first = false;
545
}
546
547
nbt.append("}");
548
return nbt.toString();
549
}
550
551
private static String formatNBTValue(Object value) {
552
if (value instanceof String) {
553
return "\"" + value + "\"";
554
} else if (value instanceof Number) {
555
return value.toString();
556
} else if (value instanceof Boolean) {
557
return value.toString() + "b";
558
}
559
return "\"" + value + "\"";
560
}
561
}
562
```
563
564
## Best Practices
565
566
### NBT Path Design
567
- Use specific paths to avoid unnecessary data access
568
- Validate NBT paths before using them in components
569
- Consider client-side performance impact of complex NBT queries
570
- Cache frequently accessed NBT data
571
572
### Security Considerations
573
- Validate entity selectors to prevent unauthorized data access
574
- Sanitize NBT data from user input
575
- Limit NBT path complexity to prevent performance issues
576
- Use appropriate permissions for NBT component access
577
578
### Error Handling
579
- Handle missing NBT data gracefully
580
- Provide fallback values for optional NBT fields
581
- Log NBT access errors for debugging
582
- Use empty components when NBT data is unavailable
583
584
### Performance Optimization
585
- Batch NBT operations when possible
586
- Use caching for frequently accessed NBT data
587
- Avoid deeply nested NBT path expressions
588
- Consider using command storage for shared data