mcdoc Language Guide
mcdoc is a schema format for describing data structures used by Minecraft, including its CODECs, JSONs, and NBTs. It is interpreted by the Spyglass language server.
Core Concepts
Primitive Types
- •
boolean- true/false values - •
byte,short,int,long- Integer types (use suffix:0b,0s,0,0L) - •
float,double- Floating-point types - •
string- Text values - •
any- Accepts any value (use sparingly)
Struct Definitions
Structs define composite types with named fields:
struct EntityData {
id: string, // Required field
pos?: [double] @ 3, // Optional field (note the ?)
/// Doc comment shown in hover
custom_name?: string,
}
Enum Definitions
Enums define fixed sets of values with a backing type:
enum(string) Direction {
Down = "down",
Up = "up",
North = "north",
}
enum(byte) DyeColorByte {
White = 0,
Orange = 1,
}
Type Aliases
Type aliases create named references to types, optionally with generics:
type Text = ::java::util::text::Text
type Tag<E> = struct {
replace?: boolean,
values: [TagEntry<E>],
}
Union Types
Union types allow a value to be one of several types (using |):
type Color = (
#[color="hex_rgb"] string |
#[color="composite_rgb"] int |
)
Arrays and Collections
[Type] // Array of any length [Type] @ 3 // Array of exactly 3 elements [Type] @ 1..5 // Array with 1-5 elements [Type] @ 1.. // Array with 1+ elements
Numeric Constraints
int @ 0..100 // Inclusive range (0 to 100) float @ 0<..1 // Exclusive lower bound (>0, <=1) float @ 0..<1 // Exclusive upper bound (>=0, <1) int @ 0.. // Minimum only (0 or greater)
Dispatch System
Dispatches map registry entries to specific type schemas:
// Direct dispatch
dispatch minecraft:entity[zombie] to struct Zombie {
...super::Monster,
CanBreakDoors?: boolean,
}
// Multiple keys to same type
dispatch minecraft:item[potion, splash_potion, lingering_potion] to struct PotionItem {
Potion?: #[id="potion"] string,
}
// Polymorphic dispatch using a type field
struct TreeDecorator {
type: #[id="worldgen/tree_decorator_type"] string,
...minecraft:tree_decorator[[type]], // Dispatch based on type field value
}
Special Dispatch Keys
- •
%unknown- Fallback for unrecognized keys - •
%none- When no key is specified - •
%fallback- Used in NBT path references
Path Variables
Path variables reference values from the data structure in dispatch keys:
- •
%parent- The containing struct (chain for ancestors:%parent.%parent) - •
%key- The current map key (in mapped types)
struct CopyState {
block: #[id="block"] string,
properties: [mcdoc:block_state_keys[[%parent.block]]], // References sibling field
}
// Arrays don't count as levels - %parent skips over them
struct Container {
modifier: ModifierType,
items: [struct {
value: minecraft:modifier[[%parent.%parent.modifier]], // %parent.%parent = Container
}],
}
Generic Dispatchers
Dispatchers can have type parameters:
// Define generic dispatcher
dispatch minecraft:int_provider[constant]<T> to struct {
value: T,
}
dispatch minecraft:int_provider[uniform]<T> to struct {
min_inclusive: T,
max_inclusive: T,
}
// Use with type parameter passed through
type IntProvider<T> = (
T |
struct {
type: #[id="int_provider_type"] string,
...minecraft:int_provider[[type]]<T>,
} |
)
// Usage with constrained type
log_length: IntProvider<int @ 0..16>,
Structural Composition
Spread Operator
The spread operator (...) includes fields from another struct:
struct Monster {
Health?: float,
}
dispatch minecraft:entity[zombie] to struct Zombie {
...super::Monster, // Include Monster fields
CanBreakDoors?: boolean, // Add zombie-specific fields
}
Inline Structs
Structs can be defined inline within fields:
struct Container {
items: [struct SlottedItem {
Slot: byte,
...ItemStack,
}],
}
Attributes
Attributes provide metadata using #[name] or #[name="value"] syntax:
Version Control
#[since="1.20"] // Available from version 1.20 #[until="1.21"] // Removed in version 1.21 #[deprecated="1.19"] // Deprecated since 1.19
Registry References
#[id="item"] string // Reference to item registry #[id(registry="block",tags="allowed")] string // Allow tags #[id(registry="texture",path="entity/")] string // Path prefix
Validation
#[color="composite_rgb"] int // RGB color as integer #[color="hex_rgb"] string // Hex color string #[regex_pattern] string // Regex pattern #[uuid] string // UUID format #[nbt=minecraft:item[[item]]] string // NBT validation
Other Attributes
#[canonical] // Preferred form in a union #[id] // Mark as identifier
Module System
Use Statements
use ::java::util::text::Text // Absolute path use super::block_state::BlockState // Parent directory use super::super::HeightmapType // Grandparent
Module Resolution
A path like use modifier::Type resolves to either:
- •
modifier.mcdoc(single-file module) — check first - •
modifier/mod.mcdoc(directory module)
Path Conventions
- •
::prefix for absolute paths from root - •
super::for parent module - •No prefix for sibling imports
Mapped Types (String Maps)
Define structs with dynamic string keys:
struct Lang {
[#[translation_key(definition=true)] string]: #[translation_value] string,
}
struct Criteria {
[#[criterion(definition=true)] string]: AdvancementCriterion,
}
Comments
// Single-line comment (not included in output) /// Doc comment (appears in hover/autocomplete) /// Multiple lines supported field_name: Type,
Best Practices
- •Naming: Use PascalCase for NBT/CODEC structs, snake_case for JSON fields
- •Avoid unnecessary doc comments - Only document complex or non-obvious fields
- •Use string enums when a string union changes between MC versions
- •Always name dispatched structs - Named types for all dispatch targets
- •Limit nesting to 3 levels - Extract deeply nested structs
- •Use spread operator to avoid code repetition
Additional Resources
- •For complete syntax reference, see reference.md
- •For practical examples, see examples.md
- •For datapack development patterns, see datapack-usage.md
- •For modded resource schemas, see modded-resources.md